Flask 进阶二

flask中的路由系统:

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

from flask import Flask,url_for

app = Flask(__name__)

@app.route("/index/",endpoint="func")
def index():
    print(url_for("func"))  # /index/
    return "helloworld"


if __name__ == '__main__':
    app.run()

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

from flask import Flask,url_for

app = Flask(__name__)

@app.route("/index/",endpoint="func",defaults={"id":1})
def index(id):
    print(url_for("func"))  # /index/
    print(id)  # 是default内的值
    return "helloworld"


if __name__ == '__main__':
    app.run()

  strict_slashes : url地址结尾符“/”的控制, False:无论结尾是否有“/”均可以访问,True:没有则不能访问。

  redirect_to :url地址重定向:

from flask import Flask,url_for

app = Flask(__name__)

@app.route("/index/",endpoint="func",defaults={"id":1},strict_slashes=False,redirect_to="/redirect_to/")
def index(id):
    print(url_for("func"))  # /index/
    print(id)  # 是default内的值
    return "helloworld"


@app.route("/redirect_to/")
def redirect():
    return "redirect_to 重定向页面"


if __name__ == '__main__':
    app.run()

动态参数路由:

@app.route("/info/<int:id>",methods=["GET","POST"],endpoint="info")
def student_info(id):
    print(url_for("info",id=2))  # /info/2
    return f"Hello old boy {id}"   # python 3.6 新功能

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

  但是这种动态参数路由,在url_for的时候,一定要将动态参数名+参数值添加进去,否则会抛出参数错误的异常。

有路由正则,一般不用,这里也就不在提及了。

flask实例化配置:

  static_folder= “static”  静态文件目录的路径,默认当前项目中的static目录。

  

 # static_folder= “statics”

# <img src="/statics/1.png" >

  根据你设置的 static_folder的值,会以什么文件夹为默认的,不设置则为static目录

  static_url_path = None :静态文件目录的url路径,默认不写是与static_folder同名,远程静态文件时复用。

  若是设置了该条件,则可以根据此来找到文件:

  template_folder = "templates" 默认模板目录,不设置值,就是默认这样的。

  instance_path = None , 指向另一个Flask实例的路径。

  instance_relatice_config = False  , 是否加载另一个实例的配置。

  root_path = None  , 主模块所在的目录的绝对路径,默认项目目录。

app 对象配置:

from flask import Flask

app = Flask(__name__)  # type:Flask
app.config["DEBUG"] = True

上面的代码可以实现:只要我们的代码发生改动,就会自动重启Flask程序。

Flask的配置就是在 app.config 中添加一个键值对,但是你存进去的键必须是config中应该存在的,如果不再存在的话,它会默认无用,就这么放着:

  

{
    '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,
}

以上这些Key,都可以被改写,当然他们也都是有默认值存在的,如果没有特殊情况,不要改写它的默认值

修改配置的方式大约是两种:

1, 直接对app.config进行修改:

app.config["DEBUG"] = True

2 ,使用类的方式导入。

from day118flask.flask_settings import Config

flask_settings.py

class Config(object):
    DEBUG = True
    SECRET_KEY = "QINGQIU"

那么在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  # 主模块所在的目录的绝对路径,默认项目目录

send_file():

  返回文件内容,并拼接文件头。如果能够识别就展示,识别不了就自动下载下来。 

jsonify():

 相当于添加了一个返回头 : content-type:application/json

  

  普通发送到主动json的数据:

  return json.dumps("数据")

  这样你的响应头的数据类型并不会更改:

flask蓝图:

  将功能和主程序进行注册绑定和分离,就是一个不能够被run的flask实例。

  主页面:

from flask import Flask,url_for,render_template,send_file,jsonify
from day118flask.flask_settings import Config
from day118flask.flask_settings import STUDENT_DICT
from day118flask.day118 import del_stu,detail_stu

app = Flask(__name__,static_folder="statics",static_url_path="/cat",template_folder="templates")
# app.config.from_object(Config)

app.register_blueprint(del_stu.del_stu)
app.register_blueprint(detail_stu.detail_stu)

@app.route("/student/")
def student():
    return render_template("student.html",stu=STUDENT_DICT)

  html 页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>
        <table border="1px">
            <thead>
                <tr>
                    <th>NAME</th>
                    <th>AGE</th>
                    <th>GENDER</th>
                    <th>OPEATE</th>
                </tr>
            </thead>
            <tbody>
                {% for k,v in stu.items() %}
                    <tr>
                        <td>{{ v.name }}</td>
                        <td>{{ v["age"] }}</td>
                        <td>{{ v.get("gender") }}</td>
                        <td><a href="/detail/{{ k }}">查看详细</a> | <a href="/del/{{ k }}">删除</a></td>
                    </tr>
                {% endfor %}

            </tbody>
        </table>
    </div>
</body>
</html>

  蓝图页面: 

from flask import Flask, render_template, request,redirect,Blueprint
from day118flask.flask_settings import STUDENT_DICT


del_stu = Blueprint("delstu",__name__)


@del_stu.route("/del/<int:id>")
def delete(id):
    if request.method == "GET":
        STUDENT_DICT.pop(id)
        return redirect("/student/")
from flask import Flask,render_template,redirect,Blueprint,request
from day118flask.flask_settings import STUDENT_DICT

detail_stu = Blueprint("detailstu",__name__)

@detail_stu.route("/detail/<int:id>")
def detail(id):
    id = id
    stu = STUDENT_DICT.get(id)
    print(stu)
    return render_template("detail.html",stu=stu,id=id)

detail.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <table border="1px">
        <thead>
        <tr>
            <th>ID</th>
            <th>NAME</th>
            <th>AGE</th>
            <th>GENDER</th>
        </tr>
        </thead>
        <tbody>
            <tr>
                <td>{{ id }}</td>
                <td>{{ stu.name }}</td>
                <td>{{ stu["age"] }}</td>
                <td>{{ stu.get("gender") }}</td>
            </tr>

        </tbody>
    </table>
</div>
</body>
</html>

flask特殊装饰器:

  @app.before_request :在请求进入视图函数之前执行装饰的函数:

  @app.after_request:在请求返回至浏览器之前,执行装饰的函数:

from flask import Flask,url_for,render_template,send_file,jsonify
from day118flask.flask_settings import Config
from day118flask.flask_settings import STUDENT_DICT
from day118flask.day118 import del_stu,detail_stu

app = Flask(__name__,static_folder="statics",static_url_path="/cat",template_folder="templates")
# app.config.from_object(Config)

app.register_blueprint(del_stu.del_stu)
app.register_blueprint(detail_stu.detail_stu)


@app.before_request
def before_request():
    print("这里是before_request")
    return None

@app.after_request
def after_request(response):
    print("这里是after_request")
    return response

@app.route("/index/",endpoint="func",defaults={"id":1},strict_slashes=False,)
def index(id):
    print(url_for("func"))  # /index/
    return render_template("index.html")


# 这里是before_request
# /index/
# 这里是after_request
# 这里是before_request
# 这里是after_request

  errorhandler("状态码") :当遇到某个状态码时执行的函数。

@app.errorhandler(404)
def err(response):
    print(response)
    return "找不到该页面"

  before_first_request:当用户第一次发起请求时执行装饰的函数:

  除非用户改变或服务器重启,否则不会再次执行。

flash 闪现:

  flash("添加内容","index") 

  get_flashed_messages(category_filter=["index"]) 将字符串从flash中取出,并清空flash.

原文地址:https://www.cnblogs.com/stfei/p/9600783.html