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

猜你喜欢

转载自www.cnblogs.com/xujunkai/p/12349216.html