zoukankan      html  css  js  c++  java
  • Flask 轻便的web框架-1

    内容简述

    1.Flask与django对比

    • 框架对比

      Django Flask
      Admin -Model 原生无
      Model 原生无
      Form表单 原生无
      Session 有--->特殊
      第三方组件特别多
    • Flask:宗旨:以简单为基准 开发一切从简 能省则省

    2.Django与Flask的优势劣势对比:

    • django:

      • 优势:组件全,功能全,教科书
      • 劣势:占用资源,创建复杂度较高
    • Flask:

      • 优势:轻量级,速度快
      • 劣势:先天不足,第三方组件稳定性较差

    3.入门Flask

    • pip3 install Flask 不要使用工具中的插件创建Flask项目
    • 三行代码启动Flask项目

    • 附属模块:

      • jinjia2 :Jinja2是Python一个被广泛应用的模版引擎,他的设计思想来源于Django的模板引擎。
      • MarkupSafe 用于render底层,防XSS攻击
      • werkzeug ------->uwsgi一个网关接口,是PythonWSGI规范的实用函数库。使用广泛,基于BSD协议
      • BSD:"伯克利软件发行版",一整套软件发行版的统称

    4.一个简单Flask:

    from flask import Flask
    app = Flask(__name__)
    @app.route("/")
    def home():
    	return "Hello world!"
    if __name__ == '__main__':
        app.run()
    
    • route:一个装饰器,用于为给定的URL规则注册视图函数。

    5.web框架的Response三剑客:

    • HTTPResponse
    • redirect
    • render

    Content-Type:text/html 为text文本类型,要用html渲染

    • render_template
    • send_file
    • jsonify
    • render_template()
    from flask import Flask, render_template, redirect, send_file, jsonify
    app = Flask(__name__)
    
    
    @app.route("/")
    def home():
        return "Hello World I am Flask"
    
    @app.route("/index")
    def index():
        return render_template("index.html")
    
    @app.route("/login")
    def login():
        return redirect("/index")
    
    @app.route("/get_file")
    def get_file():
        return send_file("app01.py")
    
    @app.route("/get_json")
    def get_json():
        #alt + enter
        return jsonify("hello json")#返回标准Json格式字符串
    
    
    app.run()
    
    • 母版配置
      • 项目下新建templates,点击鼠标右键,Mark Directory as--->Template Folder

    6.send_file()

    • 返回是一个instance类型

    • 会自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型

    • 保留当前文件格式

    • 示例:

      from flask import Flask,send_file
      
      app = Flask(__name__)
      
      @app.route("/")
      def TestDemo():
          return send_file("demo3.py")#返回文件内容,字符串
      @app.route("/get_file")
      def get_file():
          return send_file("文咏珊.jpg")#send_file会自动是被文件类型,Content-type中添加文件类型
      @app.route("/get_music")
      def get_music():
          return send_file("音乐.mp3")#send_file会自动是被文件类型,Content-type中添加文件类型
      @app.route("/get_video")
      def get_video():
          return send_file("电影.mp4")#send_file会自动是被文件类型,Content-type中添加文件类型
      if __name__ == '__main__':
          app.run()
      
    • 浏览器特性 可识别Content-type 自动渲染

    • 不可识别的Content-type 会自动下载

    - content_type:image/jpeg  返回类型为一张图片
    - content_type:audio/mpeg:返回类型为一张图片
    - content_type :video.mp4:返回类型为一个电影
    - application/x-msdownload:返回一个可下载类型
    - Content-Type: application/json  返回一个Json
    

    7.jsonify() str

    • 返回标准格式的json字符串 先序列化json的字典,Content-type中加入Application/json
    • flask 1.1.1版本中可以直接返回字典格式无序jsonify
    
    from flask import Flask,send_file,jsonify
    
    app = Flask(__name__)
    @app.route("/get_json")
    def get_json():
        dic = {"k1":"v1"}
        return jsonify(dic)#return dic 是一样的
    
    
    if __name__ == '__main__':
        app.run()
    
    • 文件特性:

      • 凡是二进制文件的开头,都设置文件类型
    • 浏览器特性:

      • 可根据文件开头描述文件类型。识别的Content-type会自动渲染
      • 当不可识别Content-type 会自动下载

    FLASK 1.1.1之后的版本可以直接返回字典等数据类型,flask会自动帮你json序列化

    8.flask中的request

    • request.method 获取请求方式

    • request.form 获取FormData中的数据,也就是form标签

      from flask import Flask,request,render_template,Markup
      
      # request:请求上下文管理,机制的实现
      
      app = Flask(__name__)
      
      @app.route("/login",methods=["GET","POST"])
      def login():
          # 如果是get请求  返回登录页面
          if request.method == "GET":
              return render_template("login.html")
      
          #如果是post请求,获取用户名密码  校验
          else:#405   表示请求方式不被允许
              # 表示直接可将ImmutableMultiDict对象转换成字典
              print(request.form.to_dict())  # 这里form指的是浏览器提交的Form表单数据(FormData)
              print("request.form------>", request.form)#   ImmutableMultiDict([('username', 'xjk'), ('password', '123')])
              print(request.form["username"])#法1:获取用户名
              print(request.form.get("username"))#法2:获取用户名
      
              if request.form.get("username") == "ywb":
                  return "Login ok!"
          return "Login 失败"
      if __name__ == '__main__':
          app.run()
      
    • request.args 获取URL中的数据 to_dict()

      #http://127.0.0.1:5000/get_json?id=1
      
      def get_json():
          print(request.args.to_dict())#{'id': '1'}
          dic = {"k1":"v1"}
          return dic
      
    • request.values 获取url和FormData中的数据(to_dict() url会覆盖FormData)

    • request.json 请求中Content-Type : application/json 请求体中的数据,被序列化到request.json中,以字典形式存放

    • request.data 请求中符合Content-Type类型,但不包含Form或FormData 保留请求体中的原始数据 是一个b""

    • request.files 获取Form中的文件

    • request.path 请求路径,路由地址

    • request.url 访问请求的完整路径包括url参数

    • request.host 主机位

    • request.cookies 字典获取浏览器请求时带上cookies

    9.文件上传

    • 注意前端form表单加 enctype="multipart/form-data"
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="my_file">
        <button type="submit">提交</button>
    </form>
    
    </body>
    </html>
    
    
    from flask import Flask, request, render_template
    import os
    app = Flask(__name__)
    
    
    @app.route("/upload",methods=["GET","POST"])
    def upload():
        #判断请求是方式
        if request.method == "GET":
            return render_template("upload.html")
        if request.method == "POST":
            my_file = request.files.get("my_file")
            print(my_file,type(my_file))#<FileStorage: '文咏珊.jpg' ('image/jpeg')> <class 'werkzeug.datastructures.FileStorage'>
            """
            stream=None,
            filename=None,
            name=None,
            content_type=None,
            content_length=None,
            headers=None,
            """
            print("stream-->",my_file.stream)#<tempfile.SpooledTemporaryFile object at 0x00000192D5D04BA8>
            print("name-->",my_file.name)#my_file
            print("content_type-->",my_file.content_type)#image/jpeg
            print("headers-->",my_file.headers)#Content-Disposition: form-data; name="my_file"; filename="文咏珊.jpg"
    
    
            filename = my_file.filename  #获取原始文件名
            file_path = os.path.join("avatar",filename)
            my_file.save(file_path)#将文件内容存入指定路径下
            return "上传完毕"
        return "上传失败"
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1",port="5000",debug=True)#debug可以在此设置,如果给定,启用或禁用调试模式。
        
        或者:
        	app.debug = True
            app.config["DEBUG"] = True
            3选1均可
    

    10jinja2

    • Flask的模版语言
      • {{ }} 引用或执行
      • {%%} 逻辑引用

    10.1函数在模版中应用

    • 返回数值相加之和
    @app.template_global()
    def add_num(a,b):
        return a+b
        
        
    模版应用:<p>{{ add_num(50,60) }}</p>
    
    • 返回html标签
    from markupsafe import Markup
    @app.template_global()
    def my_input(na,ty):
        s = f"<input type='{ty}' value='{na}'>"
        return Markup(s)
    模版应用:{{ my_input("上传","submit") }}
    
    • 直接在模版书写----->宏指令
    <div>密码:
        {% macro my_input(na,ty) %}
        <input type="{{ ty }}" name="{{ na }}">
        {% endmacro %}
    
        {{ my_input("pwd","password") }}
    </div>
    
    
    • 在模板中如何添加数据
    obj.get('name')
    obj["name"]
    
    {%for skey,svalue in obj.items()%}
    {%endfor%}
    
    {%for skey in obj%}
    {%endfor%}
    
    
    • 示例:
    <body>
        {% for i in t %}
            <div>{{ i }}</div>
        {% endfor %}
        <div>I am a index</div>
    </body>
    
    
    @app.route("/index")
    def index():
        rest = [1, 2, 3, 4, 5]
        return render_template('index.html',t=rest)
    

    12.flask中的session

    • 基于请求上下文管理机制
    #系统定义了全局变量
    session = LocalProxy(partial(_lookup_req_object, "session"))
    
    • 做一个flask的登录
      • 导入模块:from flask import session
      • 设置密钥:app.secret_key = "密钥内容"
      • 登录成功设置session
    from flask import Flask, render_template, Markup, request, session, redirect
    app = Flask(__name__)
    app.debug = True
    app.secret_key = "!@#$%^(*&^%$#@#$%&*(^$WQ*(^EWET*^EWEU"
    
    
    @app.route("/login",methods=["GET","POST"])
    def login():
        if request.method == "POST":
            print(request.form)#ImmutableMultiDict([('username', 'admin'), ('password', '123')])
            user = request.form.get("username","")
            pwd = request.form.get("password","")
            
    
            if user == "admin" and pwd == "123":
                session["user"] = user#登录成功,给session设置值
                return "登录成功"
        #交由客户端保管机制
        print(session.get("user"))
        return render_template("login.html")
    
    if __name__ == '__main__':
        app.run()
    

    13values的坑(慎用)

    #my_login.html
    <form action="?id=101&user=20" method="post">
        账号:<input type="text" name="user">
        密码:<input type="password" name="pwd">
        <input type="submit" value="提交">
    </form>
    
    #函数
    @app.route("/mlogin",methods=["GET","POST"])
    def my_login():
        if request.method == "GET":
            return render_template("my_login.html")
        if request.method == "POST":
            print(request.values)
            print(request.values.to_dict())
            return "来了老弟"
        
    #CombinedMultiDict([ImmutableMultiDict([('id', '101'), ('user', '20')]), ImmutableMultiDict([('user', 'wxx'), ('pwd', '123')])])
    #{'user': '20', 'pwd': '123', 'id': '101'}   
    
    

    • 当url和form中的Key重名的话,form中的同名的key中value会被url中的value覆盖

    14.给多个函数加同一个装饰器

    • 法1:

      import functools
      在装饰器inner里加入@functools.wraps(func)
      functools.wraps(func)相当于保留元信息
      如果不加,会报错:
      AssertionError: View function mapping is overwriting an existing endpoint function: inner
      
      不加效果等同于inner = inner(detail())
      如果加了装饰器,效果等同于inner.__name__ = func.__name__ 其函数名字得以保留
      
    • 示例:

      def wrapper(func):
          @functools.wraps(func)
          def inner(*args,**kwargs):
      
              session_key = session.get("user")
              if session_key:
                  ret = func(*args,**kwargs)
                  return ret
              else:
                  return redirect('/login')
          return inner
      
  • 相关阅读:
    下载android的linux内核的方法
    安装sunjava5jdk 提示"无法找到软件包sunjava5jdk
    Linux kernel中的annotation(转)
    2012年计划
    Android 开机图片/文字/动画的修改(转)
    2.6 内核中的计时器和列表
    linux设置默认网关
    谷歌Android被Linux内核除名(转)
    使用call_usermodehelper在Linux内核中直接运行用户空间程序(转)
    S3C2410平台上运行为例,讲解内核的解压过程
  • 原文地址:https://www.cnblogs.com/xujunkai/p/12348920.html
Copyright © 2011-2022 走看看