Flask

发布时间:2019-03-04 17:29:05编辑:auto阅读(2801)

    Flask攻略

    python三大框架预览

    Python Web框架分类
        功能分类:
            a:收发消息相关(socket)
            b:根据不同的URL执行不同的函数(业务逻辑相关的)
            c:实现动态网页(字符串的替换)
    
        Web框架分类:
            1、自己实现b,c,使用第三方的a(Django)
            2、自己实现b,使用第三方的a,c(Flask)
            3、自己实现a\b\c(Tornado)
    两个模块
    web服务器程序 《---WSGI协议---》 web应用程序
    
    1、wsgiref
    Django开发环境使用的就是wsgiref模块
    2、jinja2(Flask)
    渲染HTML页面,其实就是实现字符串的替换
    python三大框架优缺点
    
      Flask:
    
        优点: 小而精,短小精悍,第三方组件特别多
    
        缺点: 组件更新速度取决于开源者 
    
      Tornado:
    
        优点: 原生的WebSocket, 异步任务, IO非阻塞玩
    
        缺点: 没有组件,Session都没有
    
      Django:
    
       优点: 大而全,组件非常全面
    
        缺点: 太大,重量级框架,加载太大,浪费资源

    Flask的优势

    Flask中的Werkzuge原理,__call__()
    Flask的第一个Hello Flask
    Flask的 HTTPresponse render_template redirect
    Flask中的 request
    Flask中的 Jinja2 ,Markup
    Flask中的 session secret_key
    Flask中的路由系统 url_for

    Flask中Werkzuge原理

    from werkzeug.wrappers import Response, Request
    from werkzeug.serving import run_simple
    
    
    # application源码里面 get_wsgi_headers 里面有个__call__方法
    # 可以调用__call__ 在执行flk的时候执行call里面的结果
    @Request.application
    def flk(r):
        print(r.url)
        if r.url == '/123':
            asd()
        return Response("hello")
    
    # flk
    run_simple("127.0.0.1", 5500, flk)
    
    def asd():
        print('kermit')
    
    asd()

    Flask三剑客

    # HTTPresponse: return "Hello Flask"
    # render_template: return render_template("login.html") #templates
    # redirect: return redirect("/login")

    示例:

    # Httpresponse
    @app.route("/index")
    def index():
        return "Hello Flask"
    
    
    # render_template
    @app.route("/login")
    def login():
        return render_template("login.html")
    
    
    # redirect
    @app.route("/")
    def root_path():
        return redirect("/login")

    Flask需要自己开启:(流程如下)

    from flask import Flask, render_template, redirect
    app = Flask(__name__)
    app.run()  # 可以自定义ip 端口  和debug模式

    Flask的request

    request.method 获取请求方式
    request.form 获取FromData数据(通常情况下的POST请求)
    request.args    获取GET方式提交的数据
    request.files    获取file
    request.url_about    获取所有的关于URL的参数
    request.values    获取全部提交方式
    to_dict    坑,覆盖,GET覆盖POST
    request.headers    获取头部信息
    request.cookie    获取客户端cookie
    request.json    数据头:application/json
    request.data    在没有任何数据头的情况提交的POST

    Flask的模板语言

    # Flask 基于 Jinja2 做了一层小的封装,向前端传递数据 render_template 参数传递 stu = {k1:v1}
    
    {{ stu }}
        <td>{{ stu.name }}</td>
        <td>{{ stu["age"] }}</td>
        {% if stu.get("gender") == ""  %}
            <td>男</td>
        {% else %}
            <td>{{ stu.get("gender") }}</td>
        {% endif %}
        
        
        STUDENT_LIST = [
            {'name': 'stu1', 'age': 38, 'gender': ''},
            {'name': 'stu2', 'age': 73, 'gender': ''},
            {'name': 'stu3', 'age': 84, 'gender': ''}
        ]
        
        <td>{{ stu.0.name }}</td>
        <td>{{ stu[0]["age"] }}</td>
        {% if stu[0].get("gender") == ""  %}
            <td>男</td>
        {% else %}
            <td>{{ stu.0.get("gender") }}</td>
        {% endif %}
    
    
        @apl.template_global()
        def a_b_sum(a,b):
            return a+b
        {{ a_b_sum(123,234) }}
        
        @apl.template_filter()
        def a_b_c_sum(a,b,c):
            return a+b+c
        {{ 123 | a_b_c_sum(1,2) }}

    注意:安全字符串,Markup相当于模板里面有safe

    {{ input | safe }}
        Markup() : Markup("<input type='text' name='input_tag'>")

    pycharm识别模板语言的格式:设置jinja2的语言

    Session

    secret_key = "" 这个是开启session必备的参数

    form flask import session
        app.secret_key = "随意"
        session["user"] = "xxxx"
        if session.get("user")

    Jsonify

    json的转换兼容性比json模块强

    from flask import jsonify
    # import json
    # Flask的jsonify是等同于json
    # 区别是json的转换兼容性比json模块强
    @flk.route('/json')
    def get_json():
        res = {
            "user_id": 1,
            "username": "kermit",
            "password": "123"
        }
        # return json.dumps(res)
        return jsonify(res)

    Flask路由

    flk.route()
    
    "/index"  路由地址
    "/index/<nid>"   动态路由地址(视图函数需要nid参数)
    "/index/<int:nid>"   动态路由地址
    
    "/files/<filename>"     <> 里面的filename可以是本地文件内的任何一个文件全名,可以把任意存在的文件内容打印到页面上
    # 可以把所有文件内容显示到页面上面
    @flk.route('/files/<filename>')
    def files(filename):
        return send_file(filename)

    补充

    methods=["GET","POST"]   允许URL的请求方式
    endpoint="index"   反向URL操作,可以解决Inner重名的问题
    redirect_to="/index2"   服务器端页面跳转  301永久性重定向
    strict_slashes=False   可以使用"/"结尾 反之不可以
    defaults={"nid":1}   视图函数默认参数

    Flask配置

    settings.FlaskSettings

    DEBUG = True
    app.config["secret_key"] = "xxxxx"
    TESTING = True
    {
        'DEBUG': False,  # 是否开启Debug模式
        'TESTING': False,  # 是否开启测试模式
        'PROPAGATE_EXCEPTIONS': None,  # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True
        'PRESERVE_CONTEXT_ON_EXCEPTION': None,  # 一两句话说不清楚,一般不用它
        'SECRET_KEY': None,  # 之前遇到过,在启用Session的时候,一定要有它
        'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命周期(天)默认31天
        'USE_X_SENDFILE': False,  # 是否弃用 x_sendfile
        'LOGGER_NAME': None,  # 日志记录器的名称
        'LOGGER_HANDLER_POLICY': 'always',
        'SERVER_NAME': None,  # 服务访问域名
        'APPLICATION_ROOT': None,  # 项目的完整路径
        'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字
        'SESSION_COOKIE_DOMAIN': None,  # 在哪个域名下会产生session记录在cookies中
        'SESSION_COOKIE_PATH': None,  # cookies的路径
        'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否应被设置 httponly 的标志,
        'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否应被设置安全标志
        'SESSION_REFRESH_EACH_REQUEST': True,  # 这个标志控制永久会话如何刷新
        'MAX_CONTENT_LENGTH': None,  # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码
        'SEND_FILE_MAX_AGE_DEFAULT': 12,  # hours 默认缓存控制的最大期限
        'TRAP_BAD_REQUEST_ERRORS': False,
        # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,
        # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。
        'TRAP_HTTP_EXCEPTIONS': False,
        # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。
        # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。
        # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。
        # 如果这个值被设置为 True ,你只会得到常规的回溯。
        'EXPLAIN_TEMPLATE_LOADING': False,
        'PREFERRED_URL_SCHEME': 'http',  # 生成URL的时候如果没有可用的 URL 模式话将使用这个值
        'JSON_AS_ASCII': True,
        # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,
        # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。
        # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。
        'JSON_SORT_KEYS': True,
        #默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。
        # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。
        # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。
        'JSONIFY_PRETTYPRINT_REGULAR': True,
        'JSONIFY_MIMETYPE': 'application/json',
        'TEMPLATES_AUTO_RELOAD': None,
    }
    flask的整套配置项

    蓝图(Blueprint)

    from flask import Blueprint,render_template,redirect
    reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")
    
    @reg.route(
    "/reg") def reg_user():   return render_template("reg_index.html")

    from flask import Flask import reg_user app = Flask(__name__) app.register_blueprint(reg_user.reg) if __name__ == '__main__':   app.run("0.0.0.0", 9527, debug=True)

    1.Flask实例配置
    app.config.form_object("setting.FlaskSetting")
    app.DEBUG = True 开启Debug模式,该完代码不用手动重启
    app.SECRET_KEY = "xxxxx" 开启session必备参数


    2.初始化配置(Flask,Blueprint)
    template_folder="reg_temp",
    static_folder="regs",
    static_url_path="/regs"

    3.蓝图Blueprint
    在app实例中注册蓝图app.register_blueprint(reg_user.reg)
    实例化蓝图对象reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")
    蓝图对象同样与Flask对象,具备独立模板和静态目录

    from flask import Blueprint, render_template, redirect
    import DATA
    
    student_list = Blueprint('student_list', __name__, static_folder="list_static", static_url_path="/list_static")
    
    
    # 蓝图实例对象一定不能与视图函数同名
    @student_list.route('/list')
    def list():
        return render_template('index.html')

    4.before_request after_request before_frist_request
    before_request 在请求进入视图函数之前做出的处理
    after_request 在视图函数返回给用户之前做出的处理
    before_frist_request 在第一次请求进入视图函数之前做出的处理

    # 类似于Django中间件的功能
    @flk.before_request  # 在请求之前
    def be1():
        print('在请求进入App之前做出处理')
        # 判断url是不是/login
        if request.path == "/login":
            print('当前访问的页面url是:', request.path)
            # True返回None不作任何操作往下走
            return None
        if session.get("user"):
            print('userSession存在,直接访问页面!')
            return None
        else:
            print('user不存在,跳转到login页面')
            return redirect("/login")
    
    
    @flk.before_request
    def be2():
        print('执行be2')
    
    
    # 在请求之后
    @flk.after_request
    def af1(response):
        print('在此时执行了after1')
        return response
    
    
    @flk.after_request
    def af2(response):
        print('在此时执行了after2')
        return response
    
    
    # 第一次请求前执行
    @flk.before_first_request
    def be_first():
        print('第一次请求')
    
    
    # 报错发送的状态码显示的结果
    @flk.errorhandler(404)
    def error_page(arg):
        return "当前页面不存在!"

    5.errorheadler(404)
    def error_page(arg)
    错误信息头

    第一个Flask

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2018/08/27 17:19
    # @Author  : MJay_Lee
    # @File    : flask_demo_test.py
    # @Contact : limengjiejj@hotmail.com
    
    
    from flask import Flask # 导入Flask类
    
    app = Flask(__name__) # 实例化Flask对象 app
    
    @app.route("/") # app中的route装饰器
    def index(): # 视图函数
        return "first flask app"
    
    app.run("0.0.0.0",5000,debug=True) # 启动Flask Web 服务

    Flask三剑客

    Flask中的HTTPResponse

    在Flask中的HTTPResponse,在我们看来其实就是直接返回字符串

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/') # 路由
    def index(): # 视图
        return "Hello Flask" # HTTPResponse

    Flask中的redirect

    from flask import Flask,redirect
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return "Hello Flask"
    
    @app.route('/redi') # app中的route装饰器,用来指定视图函数的URL地址
    def redi(): # 视图函数
        return redirect('/') # redirect 跳转至 '/'
    
    app.run("0.0.0.0",5500,debug=True)

    Flask中的render(render_template)

    from flask import Flask,redirect,render_template
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return "Hello Flask"
    
    @app.route('/redi')
    def redi():
        return redirect('/')
    
    
    @app.route("/home") # app中route装饰器,用来指定视图函数的url地址
    def home(): # home 视图函数
        return render_template("home.html") # 渲染HTML模板发安徽HTML页面
    
    app.run("0.0.0.0",5500,debug=True)

     注意:如果要使用render_template返回渲染的模板,请在项目的主目录中加入一个目录templates文件夹

     

    Flask中的request

    每个框架中都有处理请求或收发消息的机制(request),而每个框架都有异同

    一个form表单post的提交方式

    html文件

    <form action="" method="post" novalidate>
        <input type="text" name="user" id="">
        <input type="password" name="pwd" id="">
        <input type="submit" value="提交">

    py文件

    @app.route("/home",methods=["GET","POST"]) # app中route装饰器,用来指定视图函数的url地址
    def home(): # home 视图函数
        if request.method == "POST":
            print(request.method) # POST
            print(request.form) # ImmutableMultiDict([('user', 'lmj'), ('pwd', '123')])
            print(request.form['user']) # lmj
            print(request.form['pwd']) # 123
            print(list(request.form.keys())) # ['user', 'pwd']
            return "POST请求已受理"
    
        return render_template("home.html") # 渲染HTML模板

     methods=["GET","POST"]代表这个URL地址只允许请求的方式,是个列表

    request的参数获取

    那么request的参数获取的几个方式

    html文件

    <form action="/home?id=1&age=18" method="post" novalidate>
        <input type="text" name="user" id="">
        <input type="password" name="pwd" id="">
        <input type="submit" value="提交">

    py文件

    @app.route("/home",methods=["GET","POST"]) # app中route装饰器,用来指定视图函数的url地址
    def home(): # home 视图函数
        if request.method == "POST":
            print(request.form) # form表单中的参数
    
            print('request.args'.center(50,"="))
            print(list(request.args)) # url中的参数
    
            print('request.values'.center(50,"="))
            print(list(request.values)) # 所有参数
    
            print('request.values.to_dict'.center(50,"="))
            print(request.values.to_dict()) # 将参数转为字典
    
            return "POST请求已受理"
        return render_template("home.html") # 渲染HTML模板发安徽HTML页面

    结果

    ===================request.args===================
    ['id', 'age']
    ==================request.values==================
    ['id', 'age', 'pwd', 'user']
    ==============request.values.to_dict==============
    {'user': 'lmj', 'pwd': '123', 'id': '1', 'age': '18'}

    注意:

    # 注意这里的坑来啦! 坑来啦!
    # 如果url和form中的Key重名的话,form中的同名的key中value会被url中的value覆盖
    # http://127.0.0.1:5500/req?id=1&user=cly
    print(request.values.to_dict())  # {'user': cly'pwd': '123', 'id': '1'}

    request.cookies

    print(request.cookies)
    """
    {
        'csrftoken': 'elPT8HW8Zw74NPSftY0suJEqbm3cOxEPl05f1oezHN61kikgqOgcuXWtiJCyhtuX', 
        'sessionid': 'cqfjxs0svrq2nqf9i4hdghdvqep6468w'
    }
    """

    request.headers,请求头中的参数

    print(type(request.headers)) # <class 'werkzeug.datastructures.EnvironHeaders'>
    print(request.headers)
    '''
    Host: 127.0.0.1:5500
    Connection: keep-alive
    Content-Length: 16
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Origin: http://127.0.0.1:5500
    Content-Type: application/x-www-form-urlencoded
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Referer: http://127.0.0.1:5500/home
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9,und;q=0.8,en;q=0.7
    Cookie: csrftoken=elPT8HW8Zw74NPSftY0suJEqbm3cOxEPl05f1oezHN61kikgqOgcuXWtiJCyhtuX; sessionid=cqfjxs0svrq2nqf9i4hdghdvqep6468w
    '''

    request.data,若处理不了的就变成字符串存在data里

    可以request.data,json.loads同样可以拿到里面的数据

    你一定要知道 request 是基于 mimetype 进行处理的
    
    mimetype的类型 以及 字符串儿 : http://www.w3school.com.cn/media/media_mimeref.asp
    
    如果不属于上述类型的描述,request就会将无法处理的参数转为Json存入到 data 中

    request.files,文件上传

    遇到文件上传,request.files村的就是上传的文件,但Flask在这个文件的操作中加了封装

    html文件

    <form action="" method="post" enctype="multipart/form-data" novalidate>
        <input type="file" name="file">
        <input type="submit" value="提交">
    </form>

    py文件

    @app.route("/home",methods=["GET","POST"]) 
    def home():
        if request.method == "POST":
            print(request.files) # ImmutableMultiDict([('file', <FileStorage: '待整理内容.txt' ('text/plain')>)])
            print(request.files["file"]) # <FileStorage: '待整理内容.txt' ('text/plain')>
            my_file = request.files["file"]
            my_file.save("upload_file.txt") # 保存文件,里面可以写完整路径+文件名
    
            return "POST请求已受理"
        return render_template("home.html")

    request的路径获取

        # 获取当前的url路径
        print(request.path)# /home
        # 当前url路径的上一级路径
        print(request.script_root) #
        # 当前url的全部路径
        print(request.url) # http://127.0.0.1:5000/home
        # 当前url的路径的上一级全部路径
        print(request.url_root ) # http://127.0.0.1:5000/

    request.json

    前提是你得告诉是json数据

    如果在请求中写入了 "application/json" 使用 request.json 则返回json解析数据, 否则返回 None

    Flask中的jinja2和render_template

    前端-普通数值

    <table border="1px">
        <thead>
            <tr>
                <td>姓名</td>
                <td>年龄</td>
                <td>性别</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>{{ stu.name }}</td>
                <td>{{ stu["age"] }}</td>
                <td>{{ stu.get("gender") }}</td>
            </tr>
        </tbody>
    </table>

    效果

    可以看出来,字典传入前端Jinja2 模板语言中的取值操作, 与Python中的Dict操作极为相似,并且多了一个student.name的对象操作

    前端-【列表】

    <table border="1px">
        <thead>
        <tr>
            <td>姓名</td>
            <td>年龄</td>
            <td>性别</td>
        </tr>
        </thead>
        <tbody>
        {% for stu in stu_list %}
            <tr>
                <td>{{ stu.name }}</td>
                <td>{{ stu["age"] }}</td>
                <td>{{ stu.get("gender") }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    效果

    前端-【字典】

    <table border="1px">
        <thead>
        <tr>
            <td>姓名</td>
            <td>年龄</td>
            <td>性别</td>
        </tr>
        </thead>
        <tbody>
        {% for item in stu_dict %}
            <tr>
                <td>{{ stu_dict[item].name }}</td>
                <td>{{ stu_dict[item]["age"] }}</td>
                <td>{{ stu_dict[item].get("gender") }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    效果

    render_template中可传递多个关键字

    利用 **{}字典的方式实现

    py文件

    @app.route("/allstudent")
    def all_student():
        return render_template("all_student.html", **{"student":STUDENT ,
                               "student_list" : STUDENT_LIST,
                               "student_dict": STUDENT_DICT})

    jinja2 的高阶用法

    后端文件

    from flask import Flask
    from flask import render_template
    from flask import Markup  # 导入 flask 中的 Markup 模块
    
    app = Flask(__name__)
    
    
    @app.route("/")
    def index():
        tag = "<input type='text' name='user' value='DragonFire'>"
        markup_tag = Markup(tag)  # Markup帮助咱们在HTML的标签上做了一层封装,让Jinja2模板语言知道这是一个安全的HTML标签
        print(markup_tag,
              type(markup_tag))  # <input type='text' name='user' value='DragonFire'> <class 'markupsafe.Markup'>
        return render_template("index.html", tag=markup_tag)
    
    
    app.run("0.0.0.0", 5000, debug=True)

    还有一种方式就是在前端,加上 safe

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {{ tag | safe}}  <!--  加上个 \  管道符,然后 safe  -->
    </body>
    </html>

    jinja2  模板中执行函数

    后端

    def a_b_sum(a,b):
        return a + b
    
    
    @app.route("/home",methods=["GET","POST"])
    def home():
        return render_template("home.html",tag = a_b_sum)

    前端

    {{ tag }}
    <br>
    {{ tag(10,20) }}

    效果

    补充:定义全局函数,无需后端传递给前端,jinja2就可以直接执行的函数

    后端

     

    @app.template_global() # 定义全局模板函数
    def a_b_sum(a,b):
        return a + b
    
    @app.template_filter() # 定义全局模板函数
    def a_b_c_sum(a,b,c):
        return a + b + c
    
    
    @app.route("/home",methods=["GET","POST"])
    def home():
        return render_template("home.html")

     

    前端

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {{ a_b_sum(99,1) }}
        <br>
        {{ 1 | a_b_c_sum(197,2) }}
    </body>
    </html>

    jinja2 模板复用block

    如果我们前端页面有大量重复页面,没必要每次都写,可以使用模板复用的方式复用模板

     同理于django的母版

    jinja2 模板语言中的宏定义

    前端

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    <h2>定义宏</h2>
    {% macro type_text(name,type) %}
        <input type="{{ type }}" name="{{ name }}" value="{{ name }}">
    {% endmacro %}
    <br>
    <h2>使用宏来生成input标签</h2>
    {{ type_text("one","text") }}
    {{ type_text("two","text") }}
    </body>
    </html>

    效果:

    Flask 第五篇幅

     flask-login与验证校验,待更新

    https://www.cnblogs.com/minsons/p/8045916.html
    参考笔记

    Flask 的路由系统

    route 装饰器中的参数

    methods,当前url地址,允许访问的请求方式

    @app.route("/index",methods=["GET","POST"]) # 当前url地址允许访问的请求方式
    def index():
        return render_template("index.html")

    endpoint,反向url地址,默认为视图函数名(url_for)

    from flask import Flask,render_template,url_for
    
    app = Flask(__name__)
    
    @app.route("/index",methods=["POST","GET"],endpoint="url_info") # 反向url地址,默认为视图函数名 (url_for)
    def index():
        print(url_for("url_info")) # /index
        return render_template("index.html")
    
    app.run("0.0.0.0",9527,debug=True)

    defaults,视图函数的参数默认值

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    @app.route("/index",defaults={"user_list":["lmj","cly"]})
    def index(user_list):
        return render_template("index.html",user_list=user_list) # 视图函数的默认参数
    app.run("0.0.0.0",9527,debug=True)

    strict_slashes,url地址结尾符"/"的控制,默认为True(结尾必须不能是"/")

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    @app.route("/index",strict_slashes=False) # 有效访问地址:/index 或 /index/
    def index():
        return render_template("index.html")
    app.run("0.0.0.0",9527,debug=True)

    redirect_to,url地址重定向

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    @app.route("/home")
    def home():
        return "你已跳转至home页面"
    
    @app.route("/index",redirect_to='/home')
    def index():
        return render_template("index.html")
    
    
    app.run("0.0.0.0",9527,debug=True)

    subdomain,子域名前缀subdomain="mjlee"这样写就可以得到mjlee.dream.com

    前提是app.config["SERVER_NAME"]="dream.com"

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    app.config["SERVER_NAME"] = "dream.com"
    
    @app.route("/index",subdomain="mjlee")
    def index():
        return render_template("index.html")
    
    
    app.run("0.0.0.0",9527,debug=True)
    
    # 访问地址为:mjlee.dream.com/index

    动态参数路由

    from flask import Flask,url_for
    
    app = Flask(__name__)
    
    
    # 访问地址 http://127.0.0.1:5500/index/9527
    @app.route("/index/<int:nid>",endpoint="url_info")
    def index(nid):
        print(url_for("url_info",nid=nid)) # /index/9527
        return f"success get by {nid}" # success get by 9527
    
    
    app.run("0.0.0.0",5500,debug=True)

    <int:nid>就是在url后定义一个参数接收

    但是这种动态参数路由,在url_for的时候,一定要将动态参数名+参数值添加进去(nid=nid),否则报错

    补充:

    另外还可使用正则路由,前提是正则玩的溜

    Flask 的config

     Flask的灵活体现出自其config配置,首先展示一下:

    from flask import Flask
    
    app = Flask(__name__) # type:Flask
    
    print(app.config)
    print(app.config["APPLICATION_ROOT"])
    
    
    # 默认情况下,config的28个key的详情:
    {
        'DEBUG': False,  # 是否开启DEBUG模式
        'TESTING': False,  # 是否开启测试模式
        'PROPAGATE_EXCEPTIONS': None,  # 异常传播(是否在控制台打印LOG)
        'PRESERVE_CONTEXT_ON_EXCEPTION': None, 
        'SECRET_KEY': None,  # 启用Session的时候,一定要使用它
        'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31),  # days,Session的生命周期默认31天
        'USE_X_SENDFILE': False,  # 是否启用 x_sendfile
        'LOGGER_NAME': '__main__',  # 日志记录器的名称
        'LOGGER_HANDLER_POLICY': 'always', 
        'SERVER_NAME': None,  # 服务器访问域名
        'APPLICATION_ROOT': None,  # 项目的完整路径
        'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字
        'SESSION_COOKIE_DOMAIN': None,  # 在哪个域名下会产生session记录在cookies中
        'SESSION_COOKIE_PATH': None,  # cookie的路径
        'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否应被设置 httponly 的标志
        'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否应被设置安全标志
        'SESSION_REFRESH_EACH_REQUEST': True,  # 这个标志控制永久会话如何刷新
        'MAX_CONTENT_LENGTH': None,  # 如果设置为字节数, Flask会拒绝内容大于此值的请求进入并返回403状态码
        'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200),  # 12小时,默认缓存控制的最大期限
        'TRAP_BAD_REQUEST_ERRORS': False,
        # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,
        # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。
        'TRAP_HTTP_EXCEPTIONS': False, 
        # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。
        # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。
        # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。
        # 如果这个值被设置为 True ,你只会得到常规的回溯。
        'EXPLAIN_TEMPLATE_LOADING': False, 
        'PREFERRED_URL_SCHEME': 'http',  # 生成URL的时候,如果没有可用的 URL 模式,会使用这个值
        'JSON_AS_ASCII': True,
        # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,
        # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。
        # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。
        'JSON_SORT_KEYS': True,
        #默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。
        # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。
        # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。
        'JSONIFY_PRETTYPRINT_REGULAR': True, 
        'JSONIFY_MIMETYPE': 'application/json', 
        'TEMPLATES_AUTO_RELOAD': None
    }

    app.config["DEBUG"] = True

    只要代码发生改动,自动重启Flask程序(app.run)

    在控制台打印的信息非常全面

    修改配置的方式:

    1、直接对app.config进行修改

    app.config["DEBUG"]=True

    2、使用类的方式导入

    首先要有一个settings.py的文件

    settings.py

    class FlaskSetting:
        DEBUG = True
        SECRET_KEY = "lmj"

    然后在Flask的启动文件中引用

    from flask import Flask
    
    app = Flask(__name__)
    app.config.from_object("settings.FlaskSetting")
    
    @app.route("/index")
    def index():
        return "success"
    
    app.run("0.0.0.0",9528)

    这叫做类导入配置

    以上是针对一个已经实例化的app进行配置

    那么在Flask实例化的时候,传递的参数有哪些?

    其实可以理解为对Flask实例进行的初始配置,如下:

    static_folder = 'static',  # 静态文件目录的路径 默认当前项目中的static目录
    static_host = None,  # 远程静态文件所用的Host地址,默认为空
    static_url_path = None,  # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
    # host_matching是否开启host主机位匹配,是要与static_host一起使用,如果配置了static_host, 则必须赋值为True
    # 这里要说明一下,@app.route("/",host="localhost:5000") 就必须要这样写
    # host="localhost:5000" 如果主机头不是 localhost:5000 则无法通过当前的路由
    host_matching = False,  # 如果不是特别需要的话,慎用,否则所有的route 都需要host=""的参数
    subdomain_matching = False,  # 理论上来说是用来限制SERVER_NAME子域名的,但是目前还没有感觉出来区别在哪里
    template_folder = 'templates'  # template模板目录, 默认当前项目中的 templates 目录
    instance_path = None,  # 指向另一个Flask实例的路径
    instance_relative_config = False  # 是否加载另一个实例的配置
    root_path = None  # 主模块所在的目录的绝对路径,默认项目目录

    这里面,我们常用的参数有

    static_folder = 'static',  # 静态文件目录的路径 默认当前项目中的static目录
    static_url_path = None,  # 静态文件目录的url路径 默认不写是与static_folder同名,远程静态文件时复用
    template_folder = 'templates'  # template模板目录, 默认当前项目中的 templates 目录

    Flask 的蓝图

     (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

     

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

     

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

     

    (老子是写你麻痹祖宗!两个系统来回切换写一篇博客真的是天坑!!!一天的工作记录全没了!)

     

关键字

上一篇: Vue实例

下一篇: 面向对象以及三大特性