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

    内容叙述

    • endpoint

      • endpoint相当于django里面的别名,可以用于反向解析url
      • Mapping 路由地址和endpoint - 路由地址和视图函数Mapping endpoint在同一个app中不能出现重复,默认值是视图函数名(一个装饰器装饰多个函数,endpoint命名不能一样否则报错,路由也不能一样,否则第二个匹配不到)
      from flask import Flask,redirect
      
      app = Flask(__name__)
      
      def warp(func):
          def inner(*args,**kwargs):
              return redirect("/home")
          return inner
      
      @app.route("/temp1",endpoint="temp1")
      @warp
      def temp1():
          return "I am temp1"
      
      @app.route("/temp2",endpoint="temp2")
      @warp
      def temp2():
          return "I am temp2"
      
      @app.route("/home")
      
      def home():
          return "I am home"
      
      if __name__ == '__main__':
          app.run(debug=True)
          
      #解析:多个装饰器装饰函数,从下往上执行,一个装饰器装饰多个函数,会报错,错误类型如下
      AssertionError: View function mapping is overwriting an existing endpoint function: inner
      #视图函数正在覆盖现有的端点函数,如果加了endpoint等同于inner.__name__ = func.__name__ 其函数名字,但只是改了一下名字是不行的,Flask内部方法进行此类操作通过endpoint,具体详见源码解析
      
    • url_for

      • 反向获取url地址,默认为视图函数名
      from flask import url_for
      @app.route("/info",methods=["GET","POST"],endpoint="r_info")
      def student_info():
      	print(url_for("r_info"))#/info
      	return "hello"
      

    1.路由配置:

    • Flask中的路由

      @app.route(配置路由)
      
    • rule

      • 用于路由地址
      @app.route("/login")
      def login():
          ...
          
      @app.route("/home")
      def home():
          ...
      
    • methods

      • 允许进入视图函数的请求方式
      @app.route("/home",methods=["GET","POST"])
      def home():
      	...
      
    • defaults

      • 默认路由参数
      from flask import Flask,redirect
      
      app = Flask(__name__)
      
      @app.route("/h",defaults={"count":20})
      # 传入参数,否则报错
      def home(count):
          return f"200 OK {count}"
      
      if __name__ == '__main__':
          app.run()
      
    • strict_slashes

      • 是否严格遵循路由匹配规则,url地址结尾符“/”的控制False,路径“/”是否存在均可以访问,True:结尾必须不能是"/", 为True给加'/'
      #访问地址:/info
      @app.route("/info",strict_slashes=True)
      def student_info():
      	return "hello old boy info"
      
      #访问地址:/infos    或   /infos/
      @app.route("/infos",strict_slashes=False)
      def student_infos():
      	return "hellos"
      
    • redirect_to

      • 永久重定向 响应码:301,308 永久转移
      from flask import Flask,redirect
      
      app = Flask(__name__)
      
      @app.route("/h",defaults={"count":20})
      def home(count):
          return f"200 OK {count}"
      @app.route("/res",redirect_to="/h")
      def res():
          return "hello"
      
      if __name__ == '__main__':
          app.run()
      
    • 动态参数路由1

      @app.route("/temp/<page>_<id>_<type>",endpoint="temps")
      def temp(page,id,type):
          print(page,id,type)
          return "%s_%s_%s"%(page,id,type)
      
      if __name__ == '__main__':
          app.run()
      #浏览器输入http://127.0.0.1:5000/temp/23_32_43
      #返回:23 32 43
      
    • 动态参数路由2

      @app.route("/get_img/<filename>")
      def get_img(filename):
          file_path = os.path.join("img",filename)
          return send_file(file_path)
      if __name__ == '__main__':
          app.run(debug=True)
      
    from flask import url_for
    def hmoea():
    	print(url_for('homea'))
    
    rule  "/login"  路由地址
    methods  允许进入视图函数的请求方式
    endpoint Mapping路由地址和endpoint  - 路由地址和视图函数Mapping endpoint 在同一个app中不能出现重复,默认值是视图函数
    @app      def app    endpoint=app   ❌❌❌
    defaults  默认路由参数
    stric_slashes  是否严格遵循路由匹配规则
    redirect_to  永久重定向  308
    
    动态参数路由: "/get_muisc/<filename>"  def get_music(filename)可以分页,获取文件,解决分页,解决正则路由问题
    

    2.Flask初始化配置

    • 配置位置:app = Flask(__name__)
    template_folder	   模板文件存放目录
    static_folder      静态文件存放目录 默认值 是 static   默认值static
    static_url_path    静态文件访问路径 默认值 是 / + static_folder
    当修改template_folder="img" ----> 自动修改成static_url_path='/img'。除非重新自动修改成static_url_path="static"
    

    • 示例1:
    import os
    from flask import Flask,render_template,send_file
    app = Flask(__name__,template_folder="./templates",static_folder="static",static_url_path="/static")
    
    @app.route("/")
    def index():
        return render_template("index.html")
    #前端index.html页面
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <img src="/static/2.jpg" alt="">
    </body>
    </html>
    #静态文件存放目录是static, 静态文件访问路径static_url_path="/static"
    #前端通过/static/2.jpg,找到静态文件存放目录,并提取里面文件
    static_url_path 用于放静态文件路径
    static_folder 用于存放静态文件目录
    
    • 示例2:
    import os
    from flask import Flask,render_template,send_file
    app = Flask(__name__,template_folder="templates",static_folder="img",static_url_path="/static")
    
    @app.route("/")
    def index():
        return render_template("index.html")
    
    @app.route("/img/<filename>")
    def get_img(filename):
        filepath = os.path.join("img",filename)#用static_folder.
        return send_file(filepath)
    
    if __name__ == '__main__':
        app.run(debug=True)
    #前端index.html页面
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <img src="/static/1.jpg" alt="">#用static_url_path
    </body>
    </html>
    
    • 示例3:
    @app.route("/img/<filename>")
    def get_img(filename):
        print(filename)
        filepath = os.path.join("img",filename)#通过static_folder拼接图片地址。并返回send_file
        return send_file(filepath)
    

    3.Flask实例配置

    • app.config(类似于django的setting配置)

    • 参数介绍:

      ENV 当前运行虚拟环境
      debug 编辑模式
      testing 测试,日志打印
      propaagate_exceptions
      secret_key  密钥
      
      permanent_session_lifetime   session默认时间  配置的时候写的是秒
      
      server_name 配置服务所处于的域名(Nginx自己匹配)
      
      session_cookie_name  存储在浏览器session名字
      
      session_cookie_Path  
      
      JSONIFY_MIMETYPE  设置jsonify  的content-type
      
    • 创建settings.py文件

    import hashlib,time
    
    class DebugConfig(object):
        """调试模式"""
        DEBUG = True
        SECRET_KEY = "#$#sdrer"
        PERMANENT_SESSION_LIFETIME = 3600
        SESSION_COOKIE_NAME = "hello"
    
    class TestConfig(object):
        """线上测试"""
        TESTING = True
        SECRET_KEY = hashlib.md5(f"{time.time()}asdg3#¥#@#{time.time()}".encode("utf8")).hexdigest()
        PERMANENT_SESSION_LIFETIME = 3600
        SESSION_COOKIE_NAME = "BBADASD@#@#@$##!$@"
    
    
    • 导入模块,为app配置setting
    from setting import DebugConfig
    app = Flask(__name__)
    app.config.from_object(DebugConfig)#匹配配置
    

    4.Flask中的蓝图

    • Flask 中的蓝图 Blueprint(app01)
    不能被run的Flask  实例   不存在config
    

    1.创建2个蓝图

    """
    class Blueprint
    def __init__(
            self,
            name,
            import_name,
            static_folder=None,
            static_url_path=None,
            template_folder=None,
            url_prefix=None,
            subdomain=None,
            url_defaults=None,
            root_path=None,
            cli_group=_sentinel,
        ):
    """
    #blue_pic1.py
    from flask import Blueprint
    
    bp = Blueprint("app01",__name__)
    
    @bp.route("/add_user")
    def add_user():
        return "添加用户"
    
    @bp.route("/find_user")
    def find_user():
        return "查看用户"
    
    @bp.route("/drop_user")
    def drop_user():
        return "删除用户"
    
    @bp.route("/up_user")
    def up_user():
        return "修改用户"
    #blue_pic2.py
    from flask import Blueprint
    
    car_bp = Blueprint("app02",__name__,url_prefix="/car")
    #url_prefix  可指定url前缀
    
    @car_bp.route("/add_user")
    def add_user():
        return "car添加用户"
    
    @car_bp.route("/find_user")
    def find_user():
        return "car查看用户"
    
    @car_bp.route("/drop_user")
    def drop_user():
        return "car删除用户"
    
    @car_bp.route("/up_user")
    def up_user():
        return "car修改用户"
    
    • 函数导入
    from flask import Flask
    from setting import DebugConfig
    from blue_pic1 import bp
    from blue_pic2 import car_bp
    app = Flask(__name__,template_folder="template")
    
    app.config.from_object(DebugConfig)
    
    app.register_blueprint(bp)#注册蓝图
    app.register_blueprint(car_bp)#注册蓝图
    
    if __name__ == '__main__':
        app.run()
    
    • 浏览器输入:url找到对应网址

    • 小练习:url_for在蓝图应用
    from flask import Blueprint, url_for, redirect
    
    bp = Blueprint("app01",__name__)
    
    @bp.route("/bps",endpoint="bps")
    def bps():
        return redirect(url_for("app01.dd"))
    #通过url_for("蓝图标识.endpoint值")可以获得其他视图函数的rule(url路径),通过redirect(url_for("app01.dd")),可以重定向网页
    @bp.route("/bpdd",endpoint="dd")
    def bpdd():
        return "this is bpdd..."
    

    5.特殊装饰器(类似中间件)

    • @app.before_request() 在请求进入视图函数之前,做出处理

    • @app.after_request() 在响应返回客户端之前结束视图函数之后

    • be + af 请求生命周期:

      • 正常:be1->be2->vf->af2->af1
      • 异常:be1->af2->af1
      • 只要有响应的返回,af全部响应
    • @app.errorhandler(404) 错误处理

    • 特殊装饰器实例:类似于django中间件

    from flask import Flask, send_file,session
    from setting import DebugConfig
    from blue_pic1 import bp
    from blue_pic2 import car_bp
    app = Flask(__name__,template_folder="template")
    
    app.config.from_object(DebugConfig)
    
    app.register_blueprint(bp)
    app.register_blueprint(car_bp)
    
    
    @app.before_request
    def be1():
        print("I am Be1")
    
    
    @app.before_request
    def be2():
        print("I am Be2")
    
    @app.after_request
    def af1(res):
        print("I am af1")
        return res
    
    @app.after_request
    def af1(res):
        print("I am af2")
        return res
    
    
    @app.errorhandler(404)
    """监听错误,出现404错误,直接跳转baidu页面"""
    def error404(error_message):
        print(error_message)
    
        return send_file("https://www.baidu.com/")
    
    
    @app.route("/set_session")
    def set_session():
        print("舞曲")
        session["key"] = "1234556775465"
        return "session创建"
    
    @app.route("/get_session")
    def get_session():
        print(session.get("key"))
        return "session获取"
    
    
    
    if __name__ == '__main__':
        app.run()
    #I am Be1  
    #I am Be2
    #1234556775465
    #I am af2
    #I am af1
    
    be + af  请求生命周期:
    - 正常:be1->be2->vf->af2->af1
    - be1异常:be1->af2->af1
    

    6.源码解析:

    6.1解析route装饰器源码

    • pic1:

    • pic2:

    6.2解析route中methods方法

    • pic1

  • 相关阅读:
    死锁程序示例
    用Intellij打可执行jar包
    Semaphore tryAcquire release 正确的使用方法
    计算对象占用空间工具类
    mysql高效分页方案及原理
    乐视秒杀:每秒十万笔交易的数据架构解读
    mysql 联合索引(转)
    mysql中in和exists二者的区别和性能影响
    怎样避免 i f 判断过多,全复杂度较高,代码不美观的问题?
    Java中Enum类型的序列化(转)
  • 原文地址:https://www.cnblogs.com/xujunkai/p/12349216.html
Copyright © 2011-2022 走看看