虚拟环境
介绍
它是一个虚拟化,从电脑独立开辟出来的环境。通俗的来讲,虚拟环境就是借助虚拟机docker来把一部分内容独立出
来,我们把这部分独立出来的东西称作“容器”,在这个容器中,我们可以只安装我们需要的依赖包,各个容器之间互相
隔离,互不影响
作用
不同的项目使用的python版本不同,使用的其它的包不同
为了给项目一个稳定的环境。不会因为包升级,导致老版本不兼容。
下载虚拟环境(windows)
在cmd命令中
1.pip install virtualenv
2.pip install virtualenvwrapper-win
如果输入命令 workon
显示找不到文件 即安装成功
还可以指定位置设置环境变量
可以新建个环境变量:WORKON_HOME,然后里面设置默认路径
如果下载慢的话可以换个地址
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xxx
创建虚拟环境
输入命令:virtualenv 环境名
(如果有多个python版本,可以通过命令:virtualenv -p python路径 环境名,来创建虚拟环境)
如果要指定python版本,则输入:mkvirtualenv --python=python路径(到exe文件) 环境名
一些基本命令
创建虚拟环境 环境名
mkvirtualenv
进入虚拟环境
workon 环境名
退出虚拟环境
deactivate
删除虚拟环境
rmvirtualenv 环境名
进入到虚拟环境目录
cdvirtualenv 环境名
flask项目结构
python:
mtv:
model 模型
template 模板 ---》html
view 视图 起控制作用 python代码
--项目名:
|---static (静态)js css
|---templates (模板)
|---app.py (运行|启动)
简单入门
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello world'
if __name__ == '__main__':
app.run()
首先我们导入了 Flask 类。 该类的实例将会成为我们的 WSGI 应用。
接着我们创建一个该类的实例。第一个参数是应用模块或者包的名称。默认都是用__name__这个参数是必需的,这样 Flask 才能知道在哪里可以 找到模板和静态文件等东西。
然后我们使用 route() 装饰器来告诉 Flask 触发函数的 URL 。有点像java里面的@webservlet()注解也就是资源访问路径
route() 装饰器 一个参数是 URL规则,附件表 ,必须以(/)开始 这里
URL 相对 URL (又称为 内部 URL), 即不包含域名的 URL
函数名称被用于生成相关联的 URL 。函数最后返回需要在用户浏览器中显示的信息
环境
production
development
testing
配置文件
app.config里面都是以键值对的形式存在的,可以通过key-value的形式改值
app = Flask(__name__)
print(app.config)
app.config["ENV"]="development"
app.config["DEBUG"]=True
注意配置的名称必须是全大写形式,小写的变量将不被读取
或者在项目下再定义一个settings.py
ENV="development"
DEBUG=True
import settings
app = Flask(__name__)
app.config.from_object(settings)
或者使用
app.config.from_pyfile('settings')
print(app.config)
两者区别一个要加引号,一个不用加引号
run里面的参数
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
host 侦听的主机地址
port 端口号
debug true为进入调试模式,只要改变了代码,服务器会重新加载最新的代码,适用于开发环境
默认是false,适用生产环境
路由
使用 route() 装饰器来把函数绑定到 URL:
所有的路由搜索规则都是自上而下搜索,在写路由的是有定义的路由是唯一的
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
@app.route('/')如果URL配置的一样的话会从上到下选择第一个,后面的不执行
@app.route('/')
def index():
return 'Index Page'
@app.route('/')
def hello():
return 'Hello, World'
URL都是"/" 这样就只会执行第一个index,不会执行第二个
装饰器下面的函数名要不一样不然会报错
为视图绑定多个 URL
@app .route (' / hi' )
@app . route ( '/ hello')
def say hello () :
return hl>Hello Flask ' </hl> '
一个视图函数可以绑定多 URL ,比如下面的代码把 hi hello 都绑定到 say_hello ()数上,这就会为 say_hello 图注册两个路由,用户访问这两个 URL 均会触发 sayhello ()函数,
route原理
route:
def route(self, rule, **options):
def decorator(f):
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
这个装饰器其实就是将rule字符串跟视图函数进行了绑定,通过
add_url_rule()实现的绑定
add_url_rule()方法中有三个核心处理参数
rule: 定义路由规则(访问路径)
endpoiont: 定义该路由的唯一标识
view_func:与路由匹配视图显示函数
@app.route('/index')
def index():
return 'welcome everyone!'
等效的
def index():
return 'welcome everyone!'
app.add_url_rule('/index', view_func=index)
url_for
这个url_for()函数是用于构建指定函数的URL,而且url_for操作对象是函数,而不是route里的路径
如果route路由和函数名不一样而导致使用url_for()错误,千万不要去route路由
@app.route("/register")
def register():
return redirect(url_for("login")) #注意不是因为路由是/login 而是视图函数名为login
@app.route("/login")
def login():
return "login"
使用url_for在模板中加载静态文件
加载静态文件使用的是url_for函数。第一个参数需要为’static’, 第二个参数需要为一个关键字参数filename=‘静态文件路径’。 如下所示
<link rel="stylesheet" href="{{ url_for('static', filename='css/my.css') }}">
相对 URL 只能在程序内部使用 如果你想要生成供外部使用的绝对 UR ,可 以在使用 url_for ()函数时,将_external 参数设为 True
重定向
重定向是客户端的行为至少请求两次或两次以上
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
return "index"
@app.route("/register" redirect_to="/login")
def register():
return "register"
@app.route("/login")
def login():
return "login"
if __name__ == '__main__':
app.run()
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
return "index"
@app.route("/register")
def register():
return redirect(url_for("login"))
@app.route("/login")
def login():
return "login"
if __name__ == '__main__':
app.run()
相当于请求register它返回的是login
注意redirect(url_for())的里面千万别加/,其实是因为视图函数名
endpoint
也可以使用endpoint起别名
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/",endpoint='index')
def index():
return "index"
@app.route("/register")
def register():
return redirect(url_for("login"))
@app.route("/login")
def login():
return redirect(url_for('index'))
if __name__ == '__main__':
app.run()
相当于请求register它返回的是index
endpoint是一个路由标识,可以使用flask.url_for(endpoint)根据标识反向获取URL
根据标识反向获取URL
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/",endpoint='index')
def index():
print("反向URL:"+url_for("index"))
return "index"
if __name__ == '__main__':
app.run()
注意:如果在定义路由规则时没有设置endpoint标识,那么这个时候会以函数名称作endpoint名称(函数名称不会重复,所以endpoint也就不会重复)
变量规则
通过把 URL 的一部分标记为 <variable_name> 就可以在 URL 中添加变量。标记的 部分会作为关键字参数传递给函数。通过使用 < converter:variable_name> ,可以 选择性的加上一个转换器,为变量指定规则
为了确保参数可以被正常接收,接收的参数需要通过<数据类型:变量名称>的形式定义,同时在处理请求的函数中也需要设置匹配的变量名称
类型 | 说明 |
---|---|
string | (缺省值) 接受任何不包含"/"的文本 |
int | 接受正整数 |
float | 接受正浮点数 |
path | 类似 string ,但可以包含"/" |
uuid | 接受 UUID 字符串 |
any | 匹配一些列给定值中的一个元素 |
from flask import Flask
import settings
app = Flask(__name__)
app.config.from_object(settings)
data={'a':'dyk',
'b':'cb',
'c':'lfw'
}
@app.route('/')
def hello_world():
return 'Hello world'
@app.route('/index/<username>')
def index(username):
print(type(username))
return data.get(username)
if __name__ == '__main__':
app.run()
@app.route('/add1/<int:num>')
def add1(num):
print(type(num))
return str(num)
@app.route('/add2/<float:num>')
def add2(num):
print(type(num))
return str(num)
@app.route('/add3/<path:p>')
def add3(p):
print(type(p))
return p
返回值好像必须是字符串或者字典,元组,response,不然会报错
唯一的 URL / 重定向行为
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects 的 URL 是中规中矩的,尾部有一个斜杠,看起来就如同一个文件夹。 访
问一个没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜
杠。
about 的 URL 没有尾部斜杠,因此其行为表现与一个文件类似。如果访问这个 URL
时添加了尾部斜杠就会得到一个 404 错误。这样可以保持 URL 唯一,并帮助 搜索
引擎避免重复索引同一页面
简单来说就是第一个/projects/无论是访问/projects还是访问/projects/ 都可以访问
第二个/about 只有访问 /about才能访问如果访问/about/就会404报错
HTTP 方法
Web 应用使用不同的 HTTP 方法处理 URL 。当你使用 Flask 时,应当熟悉 HTTP 方法。 缺省情况下,一个路由只回应 GET 请求。 可以使用 route() 装饰器的 methods 参数来处理不同的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
如果当前使用了 GET 方法, Flask 会自动添加 HEAD 方法支持,并且同时还会 按照 HTTP RFC 来处理 HEAD 请求。同样, OPTIONS 也会自动实现
response对象
返回值:其实返回值返回的都是一个响应对象。原来每次返回一个字符串,其实底层都是返回了一个response对象
常用方法
方法/属性 | 说明 |
---|---|
headers | 相应的首部,可以像字典一样操作 |
status | 状态码,文本类型 |
status_code | 状态码,整型 |
content_type | 页面输出的解析方式 |
set_cookie() | 设置一个cookie |
response响应对象
print(response.content_type)
print(response.headers)
print(response.status_code) # 200
print(response.status) # 200 OK
from flask import Flask, Response, make_response
import settings
app = Flask(__name__)
app.config.from_object(settings)
@app.route('/')
def hello_world():
return 'Hello world'
# return 后面返回的字符串其实也是做了一个response对象的封装。最终的返回结果还是response对象
@app.route('/index1')
def index():
return Response("hahahaha") # 返回的Response对象
@app.route('/index2')
def make():
response=make_response("index2")
# 定制响应头
response.headers['name'] = 'dyk'
return response
if __name__ == '__main__':
app.run()
request请求对象
只需要导入,通过from flask import request
属性:
print(request.headers) # request对象 对象访问属性,也可以调用方法
print(request.path)
print(request.full_path)
print(request.base_url)
print(request.url)
跟请求方法相关的:
属性/方法 | 说明 |
---|---|
args | 获取get请求的参数,通过字典方式获取键值 |
blueprint | 当前蓝本的名称 |
cookies | 一个包含所有请求提交的cookies的字典 |
data | 包含字符串形式的请求 |
endpoint | 当前请求匹配的端点值 |
files | 包含所有上传文件,可以用字典的方式获取文件 |
form | 获取post请求的参数,通过字典方式获取键值 |
values | 结合了args和form属性的值 |
headers | 包含首部字段,可以以字典的形式操作 |
is_json | 判断是否json数据 |
json | 包含解析后的json数据,可以通过字典的方式获取键值 |
method | 请求的http方法 |
get
request.args 底层是字典的形式 主要获取get提交的请求参数
如果是get请求格式是这个样子的:/register?username=dyk&password=123
此时的username是form表单中表单元素的name值
print(request.args.get('username')) # 获取值
print(request.args.get('passwor'))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="/recieve" method="get">
用户名: <input type="text" name="username">br
密码:<input type="password" name="password">br
<input type="submit" value="提交">
</form>
</body>
</html>
from flask import Flask, Response, make_response, render_template, request
import settings
app = Flask(__name__)
app.config.from_object(settings)
@app.route('/')
def hello_world():
return 'Hello world'
@app.route("/register",method="['get','post']")
def register1():
# 获取模板xxx.html的内容则通过render_template()
r=render_template('register.html')
return r
@app.route("/recieve")
def recieve():
username=request.args.get('username')
password=request.args.get('password')
return ('账号'+username+'密码'+password)
if __name__ == '__main__':
app.run()
post
request.form 底层是字典的形式 主要获取post提交的请求参数
注意post提交必须在路由中进行设置,通过methods = ['GET','POST']
按照此种形式:
@app.route('/register', methods=['GET', 'POST'])
获取数据:
print(request.form) # 如果请求方法是post则需要通过request.form取值
print(request.form.get('username'))
print(request.form.get('address'))
from flask import Flask, Response, make_response, render_template, request
import settings
app = Flask(__name__)
app.config.from_object(settings)
@app.route('/')
def hello_world():
return 'Hello world'
@app.route("/register",methods=['GET','POST'])
def register1():
r=render_template('register.html')
return r
@app.route("/recieve",methods=['GET','POST'])
def recieve():
if request.method=='GET':
username=request.args.get('username')
password=request.args.get('password')
elif request.method=='POST':
username = request.form.get('username')
password = request.form.get('password')
return ('账号'+username+'密码'+password)
if __name__ == '__main__':
app.run()
视图函数的返回值:
response响应:
1。str 自动转成response对象
2。dict json
3。response对象 response对象
4。make_response() response对象
5。redirect() 重定向 302状态码
6。render_template() 模板渲染 + 模板
模板
如果想在视图函数中获取模板xxx.html的内容则通过render_template()
render_template(‘模板名称’) 返回值是一个字符串
这些html必须是写在templas目录下,否则会找不到
模板的语法:
在模板中获取view中传递的变量值:{{ 变量名key }}
render_template('模板名字',key=value,key=value)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>name:{{ username }}</div>
<div>password:{{ username }}</div>
</body>
</html>
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/",endpoint='index')
def index():
return render_template("index.html",username="dyk",password="123")
if __name__ == '__main__':
app.run()
注意当没有传递这个参数是默认是空
如果传递的是列表,元组,字典,对象,
{{ list.0 }} 同 {{ list[0] }}
{{ dict.key }} 同 {{ dict.get(key) }}
{{ girl.name }} 同 {{ 对象.属性 }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>name:{{ username }}</div>
<div>password:{{ username }}</div>
<div>{{ stu.0 }}</div>
<div>{{ stu[0] }}</div>
<div>{{ dict1.name }}</div>
<div>{{ dict1.get('name') }}</div>
<div>{{ boy1 }}</div>
<div>{{ boy1.name }}</div>
</body>
</html>
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
class boy:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return self.name
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/",endpoint='index')
def index():
stu=['dyk','cb','lfw']
dict1={'name':'dyk','age':18,'id':'1001'}
boy1=boy('dyk',18)
return render_template("index.html",username="dyk",password="123",stu=stu,dict1=dict1,boy1=boy1)
if __name__ == '__main__':
app.run()
控制块
set
set是定义的一个全局变量,在页面到处可以使用
{% set 变量名=变量值%}
with
with定义了一个局部变量,只允许在with的范围内使用
{% with 变量名=变量值%}
if
{% if 条件 %}
{% endif %}
{% if 条件 %}
条件为True
{% else %}
条件为False
{% endif %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
{% if stu|length>1 %}
<div>长度大于1</div>
{% else %}
<div>长度小于1</div>
{% endif %}
</div>
</body>
</html>
for
{% for 变量 in 可迭代的对象 %}
for循环要做的任务
{% endfor %}
变量 | 描述 |
---|---|
loop.index0 | 当前循环的次数(从0开始) |
loop.index() | 当前循环的次数(从1开始) |
loop.revindex | 到循环结束需要迭代的次数(从1开始) |
loop.revindex0 | 到循环结束需要迭代的次数(从0开始) |
loop.first | 如果是第一次迭代则为True |
loop.last | 如果是最后次迭代则为True |
loop. length | 序列中项目数 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table align="center" border="1">
{% for stu in stus%}
<tr>
<td>{{ stu.name }}</td>
<td>{{ stu.age }}</td>
<td>{{ stu.id }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
过滤器
过滤器的本质就是函数
模板语法中过滤器:
{{ 变量名 | 过滤器(*args) }}
{{ 变量名 | 过滤器 }}
常见的过滤器
字符串过滤器
safe
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
msg="<h1>这只是一个测试</h1>"
return render_template("test.html",msg=msg)
if __name__ == '__main__':
app.run()
当没使用过滤器时页面的结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ msg }}
</body>
</html>
使用过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ msg | safe}}
</body>
</html>
就可以正常的加粗了
使用safe的场景在渲染数据的时候,数据里面带标签了,不想让标签转义,保留 效果,就使用safe
capitalize
单词的首字母大写
{{ msg1|capitalize}}
#Hello
lower和upper
大小写的转换
{{ msg1|lower}} #hello
{{ msg1|upper}} #HELLO
title
一句话中每个单词的首字母大写
{{ msg1|title}} #Hello
reverse
{{ msg1|reverse}} #olleh
翻转
format
{{ '%s is %d years old' | format('dyk',18) }} #dyk is 18 years old
列表
列表过滤器的使用
{{ msg | first }}<br>
{{ msg | last }}<br>
{{ msg | length }}<br>
{#{{ msg | sum }} 整型的计算 #}
{{ [1,3,5,7,9] | sum }}<br>
{{ [1,8,5,7,3] | sort }}<br>
字典
users=[{'name':'dyk','age':18,'id':'1001'},
{'name':'dyk','age':18,'id':'1001'},
{'name':'dyk','age':18,'id':'1001'},
{'name':'dyk','age':18,'id':'1001'}]
{% for v in users.0.values() %} ---->获取值
<p>{{ v }}</p>
{% endfor %}
<hr>
{% for k in users.0.keys() %} ----》获取键
<p>{{ k }}</p>
{% endfor %}
<hr>
{% for k,v in users.0.items() %} ---》获取键值
<p>{{ k }}---{{ v }}</p>
{% endfor %}
自定义过滤器
如果自定义的过滤器和系统自带的重名会把系统的覆盖了
通过flask模块中的add_template_filter方法
a. 定义函数,带有参数和返回值
b. 添加过滤器 app.add_template_filter(function,name='')
c. 在模板中使用: {{ 变量 | 自定义过滤器 }}
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
msg="<h1>这只是一个测试</h1>"
msg1="hello"
return render_template("test.html",msg=msg,msg1=msg1)
def my_len(value):
return len(value)
app.add_template_filter(my_len,'mylen')
if __name__ == '__main__':
app.run()
使用装饰器完成
a. 定义函数,带有参数和返回值
b. 通过装饰器完成,@app.template_filter('过滤器名字')装饰步骤一的函数
c. 在模板中使用: {{ 变量 | 自定义过滤器 }}
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
msg="<h1>这只是一个测试</h1>"
msg1="hello"
return render_template("test.html",msg=msg,msg1=msg1)
@app.template_filter('mylen')
def my_len(value):
return len(value)
if __name__ == '__main__':
app.run()
模板继承
需要模版继承的情况:
1. 多个模板具有完全相同的顶部和底部
2. 多个模板具有相同的模板内容,但是内容中部分不一样
3. 多个模板具有完全相同的模板内容
block语法
一般在父模板中,定义一些公共的代码,子模板可能要根据的需求不同的来实现,这时父模板就应该提供一个接口,也就是块,让子模板来实现。
标签:
{% block 名字 %}
代码
{% endblock %}
继承语法
{% extends 父模板的名称 %}
模板继承步骤
1.定义父模板
2.子模板继承父模板
父模板:
1。 定义一个base.html的模板
2。 分析模板中哪些是变化的比如:{% block title %}父模板的title{% endblock %}
对变化的部分用block进行"预留位置"也称作:挖坑
3。注意:样式和脚本 需要提前预留
{% block mycss %}{% endblock %}
{% block myjs %}{% endblock %}
子使用父模板:
1。 {% extends '父模板的名称' %}将父模板继承过来
2。 找到对应的block(坑)填充,每一个block都是有名字的。
注意
子模板中的代码第一行应该是extends
子模板中,如果实现自己的代码应该放到block中,如果放到其他地方,就不会被渲染
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block title %}<title>父模板</title> {% endblock %}
<style>
.head{
height: 100px;
background-color: pink;
}
.middle{
height: 600px;
background-color: skyblue;
}
.foot{
height: 100px;
background-color: greenyellow;
}
</style>
{% block mycss %}{% endblock %}
</head>
<body>
<div class="head">头部</div>
<div class="middle">中部
{% block middle %}
<button class="btn">点我试试</button>
{% endblock %}
</div>
<div class="foot">尾部</div>
{% block myjs %}{% endblock %}
</body>
</html>
index.html
{% extends 'base.html' %}
{% block title %}
<title>子模板</title>
{% endblock %}
{% block mycss %}
<style>
.head{
height: 50px;
background-color: yellow;
}
.middle{
height: 300px;
background-color: blueviolet;
}
.foot{
height: 50px;
background-color: fuchsia;
}
</style>
{% endblock %}
{% block myjs %}
<script>
var btn=document.querySelector(".btn")
btn.onclick=function () {
alert("求求了别点我")
}
</script>
{% endblock %}
from flask import Flask, Response, make_response, render_template, request, redirect, url_for
import settings
app=Flask(__name__)
app.config.from_object(settings)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/base")
def base():
return render_template("base.html")
if __name__ == '__main__':
app.run()
效果如下
index.html在继承了base.html基础上把高度都缩小到一半,并改变了颜色,并且给父模板的按钮添加了js
那如果想引入外部的js,css图片等等能
整体结构
{% block mycss %}
<style>
.head{
height: 50px;
background-color: yellow;
}
.middle{
height: 300px;
background-color: blueviolet;
}
.foot{
height: 50px;
background-color: fuchsia;
}
</style>
<link rel="stylesheet" href="../static/css/mycss.css">
{% endblock %}
直接相对路径是可以的,但是如果以后结构更复杂了,就不行所以我们还是可以用 url_for
<link rel="stylesheet" href="{{ url_for('static',filename='css/mycss.css') }}">
同理,js和图片也可以用url_for直接定位到static文件夹
include
include: 包含
在A,B,C页面都共同的部分,但是其他页面没有这部分。
这个时候考虑使用include
步骤:
1。先定义一个公共的模板部分,xxx.html
2。谁使用则include过来, {% include '文件夹/xxx.html' %}
macro
宏,有点类似函数
作用
1。把它看作是jinja2的一个函数,这个函数可以返回一个HTML字符串
2。目的:代码可以复用,避免代码冗余
定义两种方式:
1。在模板中直接定义:
类似: macro1.html 中定义方式
2。将所有宏提取到一个模板中:macro.html
谁想使用谁导入:
{% import 'macro.html' as xxx %}
{{ xxx.宏名字(参数) }}
定义宏
{% macro form(action,value='登录',method='post') %}
<form action="{{ action }}" method="{{ method }}">
<input type="text" placeholder="用户名" name="username">
<br>
<input type="password" placeholder="密码" name="password">
<br>
<input type="submit" value="{{ value }}">
</form>
{% endmacro %}
调用宏
本模板的宏
{{ form('/') }}
调用外部的宏
{% import 'macro/macro.html' as func %}
{{ func.form('/welcome',value='注册') }}
蓝图
蓝图(blueprint):用于实现单个应用的视图、模板、静态文件的集合
蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能。 在Flask中,使用蓝图可以帮助我们实现模块化应用的功能
蓝图也是一种路由的表现方式
使用蓝图可以分为三个步骤
1.创建一个蓝图的包,例如user,并在views.py文件中创建蓝图对象
user_bp=Blueprint('user',__name__)
# 其中第一个参数是蓝图的名字,第二个参数是import_name
2.在这个蓝图目录下, ,保存当前蓝图使用的视图函数
@user_bp.route('/')
def user_center():
return '用户中心'
@user_bp.route('/register')
def user_register():
return '用户注册'
@user_bp.route('/login')
def user_login():
return '用户登录'
3.导入并在app对象上注册这个users蓝图对象
from apps.user.view import user_bp
#将蓝图对象绑定到app上面
app.register_blueprint('user_bp')
注意如果在蓝图里面使用url-for 要记得带蓝图的名字,例如
user_bp=Blueprint('user',__name__)
<form action='{{ url_for('user.register') }}' method="post">
url_prefix参数的使用
user_bp1 = Blueprint('user', __name__, url_prefix='/user')
@user_bp1.route('/')
def index():
return render_template('base.html')
当上面的url_prefix修改过之后,这里的路由默认/user开头
例如要访问/这个路由 如果URL只输入http://127.0.0.1:5000/就会找不到,而应该输入http://127.0.0.1:5000/user/
蓝图综合
整体结构
1. 创建项目并设置settings.py文件
2. 删除app.py中的部分内容
3. 创建包apps,并在包中__init__.py中创建app的工厂函数
def create_app():
app = Flask(__name__) # app是一个核心对象
app.config.from_object(settings) # 加载配置
# 蓝图
return app
4. 在apps中创建项目的程序包比如user,goods,order等
5. 以user为例,在user包中创建view.py,在view.py中定义蓝图
在user包定义model.py
user_bp = Blueprint('user', __name__)
# 其中第一个参数是蓝图的名字,第二个参数是import_name
6.使用蓝图定义路由和视图函数
@user_bp.route('/')
def user_center():
return render_template('user/show.html', users=users)
注意在蓝图中进行了模板的加载,而模板的文件夹默认是跟flask对象是同级的,如果不是同级的注意在Flask对象创建的时候初始化设置
因为现在我是在apps里的__init__.py里面建立的flask,所以它和templates和static不是同一级的,修改默认的初始化,才能成功访问
def create_app():
app = Flask(__name__,template_folder='../templates',static_folder='../static') # app是一个核心对象
app.config.from_object(settings) # 加载配置
# 蓝图
app.register_blueprint(user_bp) # 将蓝图对象绑定到app上
print(app.url_map)
return app
定义模板
在templates里定义一个user文件夹,在user文件夹里面定义一些和user相关的模板
在templates里面定义base.html的模板
各个模块代码如下
apps里的
init.py
from flask import Flask
import settings
from apps.user.view import user_bp
def create_app():
#app是一个核心对象
app = Flask(__name__,template_folder="../templates",static_folder="../static")
#加载配置
app.config.from_object(settings)
#将蓝图对象绑定到app上面
app.register_blueprint(user_bp)
return app
apps里user
user里面的
model.py
class User:
def __init__(self,username,password):
self.username=username
self.password=password
def __str__(self):
return self.username
user里面的
view.py
from flask import Blueprint, request, render_template, redirect
from apps.user.model import User
user_bp=Blueprint('user',__name__)
#列表保存的是一个一个的用户对象
users=[]
@user_bp.route('/')
def user_center():
return render_template('user/show.html', users=users)
@user_bp.route('/register',methods=['GET','POST'])
def user_register():
if(request.method=='POST'):
username=request.form.get('username')
for u in users:
if u.username==username:
return render_template("user/register.html",msg="用户名已存在")
password=request.form.get('password')
u=User(username,password)
# 添加进用户列表
users.append(u)
return redirect("/")
return render_template("user/register.html")
@user_bp.route('/login')
def user_login():
return '用户登录'
@user_bp.route('/del')
def deluser():
username=request.args.get('username')
for user in users:
if(user.username==username):
users.remove(user)
return redirect("/")
else:
return "删除失败"
@user_bp.route('/update',methods=['POST','GET'])
def user_update():
if request.method=='POST':
username=request.form.get('username')
password = request.form.get('password')
for user in users:
if(user.username==username):
users.remove(user)
u=User(username,password)
users.append(u)
return redirect("/")
else:
return "修改失败"
else:
username=request.args.get('username')
for user in users:
if (user.username == username):
return render_template("user/update.html",user=user)
templates里的模板
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block title %}<title>基本模板 </title>{% endblock %}
{% block mycss %}
{% endblock %}
</head>
<body>
<div class="head"></div>
<div class="middle">
{% block middle %}
{% endblock %}
</div>
<div class="footer"></div>
{% block myjs %}
{% endblock %}
</body>
</html>
templates里的user里的
show.html
{% extends "base.html" %}
{% block middle %}
<h1>用户信息</h1>
<h4>当前用户人数:{{ users|length }}</h4>
<table border="1" cellpadding="1" cellspacing="0">
{% for user in users %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ user.username }}</td>
<td>{{ user.password }}</td>
<td><a href="javascript:;" onclick="update( '{{ user.username }} ')">修改</a></td>
<td><a href="javascript:;" onclick="del( '{{ user.username }} ')">删除</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% block myjs %}
<script>
function del(name) {
location.href="/del?username="+name;
}
function update(name) {
location.href="/update?username="+name;
}
</script>
{% endblock %}
regsiter.html
{% extends 'base.html' %}
{% block title %}
用户注册
{% endblock %}
{% block middle %}
{{ msg }}
<form action="/register" method="post">
<p>用户名<input type="text" name="username"></p>
<p>密码<input type="password" name="password"></p>
<input type="submit" value="注册">
</form>
{% endblock %}
update.html
{% extends "base.html" %}
{% block title %}
用户修改
{% endblock %}
{% block middle%}
<form action="/update" method="post">
<p>用户名<input type="text" name="username" value="{{ user.username }}"></p>
<p>密码<input type="password" name="password" value="{{ user.password }}"></p>
<input type="submit" value="更新">
</form>
{% endblock %}
flask-script
Flask-script的作用是可以通过命令的形式来操作flask,例如通过命令跑一个开发版本的服务器、设置数据库,定时任务等。
pip install flask-script
使用里面的Manager进行命令得到管理和使用:
manager = Manager(app=app)
manager.run() ---->启动
from flask_script import Manager
from apps import create_app
app=create_app()
manager=Manager(app=app)
if __name__ == '__main__':
manager.run()
在终端里输入 python app.py runserver
还可以加一些参数
使用命令在终端:
python app.py runserver ---->Runs the Flask development server
python app.py runserver -h 0.0.0.0 -p 5001
自定义添加命令
@manager.command
def init():
print('初始化')
python app.py init
flask连接数据库
安装:
pip install pymysql 建公路
pip install flask-sqlalchemy 实现ORM映射
pip install flask-migrate 发布命令工具
步骤:
1。配置数据库的连接路径
#mysql+pymysql://user:password@hostip:port/databasename
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/db3'
settings.py
class Config:
ENV = 'development'
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/db3'
2。创建包ext
__init__.py中添加:
db = SQLAlchemy() ---->必须跟app联系
def create_app():
....
db.init_app(app)
return app
ext包的__init__.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
apps的__init__.py
from flask import Flask
import settings
from apps.user.view import user_bp
from ext import db
def create_app():
#app是一个核心对象
app = Flask(__name__,template_folder="../templates",static_folder="../static")
#加载配置
app.config.from_object(settings.Config)
#将蓝图对象绑定到app上面
app.register_blueprint(user_bp)
db.init_app(app=app)
return app
创建模型:
models.py
模型就是类,经常称作模型类
class User(db.Model): ------> user表
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(15), nullable=False)
password = db.Column(db.String(12), nullable=False)
phone = db.Column(db.String(11), unique=True)
rdatetime = db.Column(db.DateTime, default=datetime.now)
模型类对应的表名由Flask-SQLlchemy生成,默认为类名的小写形式,也可以显示的通过__tablename__属性自己来指定
常见的数据类型:
数据类型 | 说明 |
---|---|
Integer | 整型 |
String(size) | 字符串类型,务必指定大小 |
Text | 长文本类型 |
DateTime | 日期时间 |
Float | 浮点类型 |
Boolean | 布尔类型 |
PickleType | 存储pickle类型 主要跟序列化有关 |
LargeBinary | 存储大的二进制类型 |
可选的:
primary_key=True 主键
autoincrement=True 自增
nullable=False 不允许为空
unique=True 唯一
default=datetime.now 默认值 可以设置成当前系统时间或者其他的值
db.ForeignKey('主表表名.主键名') 外键 同步到数据库的外键关系
特别注意 在app.py 中导入模型:from apps.user.models import User
默认在数据库中建立的表的名字是模型名的小写,自定义列表名
外键
定义关系的第一步是创建外键,外键是用来在A表存储B表的主键以便和B表建立联系的关系字段,因为外键只能存储单一数据,所以外键总是在"多"这一侧定义,就拿作者和文章举例,一个作者可以有多篇文章,所以我们需要为每篇文章添加外键存储作者的主键以指向对应的作者,
在模型里面写上
__tablename__='表名'
定义关系属性 relationship(关联的类名)
关系属性的名称没有限制,它相当于一个快捷查询,不会作为字段写入数据库
通过backref参数来代替反向关系属性 backref='反向关系属性名'
# 增加一个字段
articles = db.relationship('Article', backref='user')
backref是定义反向引用,给Article这个模型添加一个user属性
注意relationship()作用主要是在view和template中体现的,而Column是在数据库中体现的
多表查询
两个表两两通过第三个表关联起来
# tags = db.Table('user_goods',
# db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
# db.Column('goods_id', db.Integer, db.ForeignKey('goods.id')),
# db.Column('number',db.Integer,default=1)
# )
# 关系表: user与goods之间的关系
class User_goods(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
goods_id = db.Column(db.Integer, db.ForeignKey('goods.id'))
number = db.Column(db.Integer, default=1)
users = db.relationship('User', backref='goodslist', secondary='user_goods')
如果没有外键foreignkey可以通过第三张表关联起来
多对多的关系,要通过一个中间表进行关联
5.使用命令:
a.
在app.py 中导入模型:from apps.user.models import User
b. 在终端使用命令:db
python3 app.py db init -----》 产生一个文件夹migrations
python3 app.py db migrate -----> 自动产生了一个版本文件
项目
| ---apps
| ---ext
| ---migrations python3 app.py db init 只需要init一次
|---versions 版本文件夹
|---71edde7ee937_.py ---》 python3 app.py db migrate 迁移
|---cc0dca61130f_.py
python3 app.py db upgrade 同步
python3 app.py db downgrade 降级
init命令只需要执行一次,只要生成了migrations文件夹,那怕改变了模型也不需要在init了,只需要migrate,upgrade,就行了
创建表:
db.create_all()
删除表:
db.drop_all()
添加数据
# 模板,视图与模型结合
# 1. 找到模型类并创建对象
user = User()
# 2. 给对象的属性赋值
user.username = username
user.password = password
user.phone = phone
# 添加
# 3.将user对象添加到session中(类似缓存)
db.session.add(user)
# 4.提交数据
db.session.commit()
view.py
from flask import Blueprint, request, render_template
from apps.user.models import User
from exts import db
user_bp = Blueprint('user', __name__)
@user_bp.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
repassword = request.form.get('repassword')
phone = request.form.get('phone')
if password == repassword:
# 与模型结合
# 1. 找到模型类并创建对象
user = User()
# 2. 给对象的属性赋值
user.username = username
user.password = password
user.phone = phone
# 添加
# 3.将user对象添加到session中(类似缓存)
db.session.add(user)
# 4.提交数据
db.session.commit()
return '用户注册成功!'
else:
return '两次密码不一致!'
return render_template('user/register.html')
models.py
from datetime import datetime
from exts import db
class User(db.Model):
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
username=db.Column(db.String(20),nullable=False)
password=db.Column(db.String(20),nullable=False)
phone=db.Column(db.String(11),unique=True)
registertime=db.Column(db.DateTime,default=datetime.now())
def __str__(self):
return self.username
app.py
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
from apps import create_app
from apps.user.models import User
from exts import db
app=create_app()
manager=Manager(app=app)
migrate=Migrate(app=app,db=db)
manager.add_command('db',MigrateCommand)
if __name__ == '__main__':
manager.run()
settings.py
class Config:
DEBUG = True
# mysql+pymysql://user:password@hostip:port/databasename
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/db4'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
class DevelopmentConfig(Config):
ENV = 'development'
class ProductionConfig(Config):
ENV = 'production'
DDEBUG = False
apps的 init.py
from flask import Flask
import settings
from apps.user.view import user_bp
from exts import db
def create_app():
app=Flask(__name__,template_folder='../templates',static_folder='../static')
app.config.from_object(settings.DevelopmentConfig)
db.init_app(app=app)
app.register_blueprint(user_bp)
return app
exts的__init__.py
from flask_sqlalchemy import SQLAlchemy
db=SQLAlchemy()
查询
无条件查询:模型类.query.查询执行器
条件查询:模型类.query.过滤器.查询执行器
常用过滤器如下:
过滤器 | 说明 |
---|---|
filter(条件) | 返回符合该条件的查询集,BaseQuery对象 |
filter_by() | 返回符合该等值条件的查询集 |
limit | 使用指定的值限定原查询返回的结果 |
offset() | 偏移原查询返回的结果,返回一个新查询集 |
order_by() | 根据字段进行排序,默认是正序,返回新查询集,desc可以反序 |
group_by() | 根据字段进行分组,返回新查询集合 |
常用查询执行器如下:
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果未查到,返回None |
first_or_404() | 返回查询的第一个结果,如果未查到,返回404 |
get() | 返回指定主键对应的行,如不存在,返回None,否则返回一个用户对象 |
get_or_404() | 返回指定主键对应的行,如不存在,返回404 |
count() | 返回查询结果的数量 |
paginate() | 返回一个Paginate对象,分页对象,它包含指定范围内的结果,参数一:第几页,参数二:每页个数,参数3:如果没有该页数返回False |
模型类.query.all()
等价于
select * from user;
如果有条件的查询:
模型类.query.filter_by(字段名 = 值)
等价于
select * from user where 字段=值;
模型类.query.filter_by(字段名 = 值).first()
等价于
select * from user where 字段=值 limit..;
query.filter() 与query.filter_by()的区别
模型类.query.filter() 里面是布尔的条件 模型类.query.filter(模型名.字段名 == 值)
filter比filter_by的功能更强大,支持比较运算符,支持or_、in_等语法
模型类.query.filter_by() 里面是一个等值 模型类.query.filter_by(字段名 = 值)
filter_by: 用于查询简单的列名,不支持比较运算符
如果要检索的字段是字符串(varchar,db.String):
User.username.startswith('')
User.username.endswith('')
User.username.contains('')
User.username.like('')
User.username.in_(['','',''])
User.username == 'zzz'
如果要检索的字段是整型或者日期类型:
User.age.__lt__(18)
User.rdatetime.__gt__('.....')
User.age.__le__(18)
User.age.__ge__(18)
User.age.between(15,30)
1. 模型类.query.filter().all() -----> 列表
2. 模型类.query.filter().first() ----->对象
模糊查询
User.query.filter(User.username.endswith('z')).all()
# select * from user where username like '%z';
User.query.filter(User.username.startswith('z')).all()
# select * from user where username like 'z%';
User.query.filter(User.username.contains('z')).all()
# select * from user where username like '%z%';
多条件:
from sqlalchemy import or_, and_,not_
并且: and_
或: or_
非: not_
User.query.filter(or_(User.username.like('z%'), User.username.contains('i'))).all()
等价于
select * from user where username like 'z%' or username like '%i%';
User.query.filter(and_(User.username.contains('i'), User.rdatetime.__gt__('2020-05-25 10:30:00'))).all()
等价于
select * from user where username like '%i%' and rdatetime < 'xxxx'
__gt__,__lt__,__ge__(gt equal),__le__ (le equal) ----》通常应用在范围(整型,日期)也可以直接使用
> < >= <= !=
User.query.filter(not_(User.username.contains('i'))).all()
排序:order_by
注意:order_by(参数):
1。 直接是字符串: '字段名' 但是不能倒序
2。 填字段名: 模型.字段 order_by(-模型.字段) 倒序
user_list = User.query.filter(User.username.contains('z')).order_by(-User.rdatetime).all() # 先筛选再排序
user_list = User.query.order_by(-User.id).all() 对所有的进行排序
限制: limit
# limit的使用 + offset
user_list = User.query.limit(2).all() 默认获取前两条
user_list = User.query.offset(2).limit(2).all() 跳过2条记录再获取两条记录
删除
两种删除:
1。逻辑删除(定义数据库中的表的时候,添加一个字段isdelete,通过此字段控制是否删除)
id = request.args.get(id)
user = User.query.get(id)
user.isdelete = True
db.session.commit()
2。物理删除(彻底从数据库中删掉)
id = request.args.get(id)
user = User.query.get(id)
db.session.delete(user)
db.session.commit()
更新:
id = request.args.get(id)
user = User.query.get(id)
# 修改对象的属性
user.username= xxxx
user.phone =xxxx
# 提交更改
db.session.commit()
flask-bootstrap
安装
pip install flask-bootstrap
注意 flask-bootstrap和bootstrap-flask不兼容,不要同时下载
进行配置
在exts的__init__.py
from flask-bootstrap import Bootstrap
bootstrap = Bootstrap()
在apps的__init__.py中进行初始化:
# 初始化bootstrap
bootstrap.init_app(app=app)
flask-bootstrap内置站位块
占位块名 | 描述 |
---|---|
doc | 整个文档 |
html_attribs | html标签属性 |
html | html标签内容 |
head | html标签内容 |
title | title标签内容 |
metas | meta标签内容可以定义多个 |
styles | style标签内容可以定义多个 |
body_attribs | body标签属性可以定义多个 |
body | body标签内容,定义要显示的HTML代码 |
navbar | 菜单栏定义 |
content | bootstrap内容定义 |
scripts | scripts标签内容,可以定义多个 |
3。内置的block:
{% block title %}首页{% endblock %}
{% block navbar %} {% endblock %}
{% block content %} {% endblock %}
{% block styles %} {% endblock %}
{% block srcipts %} {% endblock %}
{% block head %} {% endblock %}
{% block body %} {% endblock %}
继承bootstrap默认的base模板
{% extends "bootstrap/base.html" %}
继承
{% block styles %}
{{ super() }}
<style>
.....
</style>
{% endblock %}
flask-会话机制
cookie
在网站中,HTTP请求是无状态的。也就是说,即使第一次用户访问服务器并登录成功后,第二次请求服务器依然不知道当前发起请求的是哪个用户。cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,浏览器将这些数据保存在本地。当用户发起第二次请求的时候,浏览器自动的将上次请求得到的cookie数据携带给服务器,服务器通过这些cookie数据就能分辨出当前发起请求的是哪个用户了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4K,因此使用cookie只能存储一些少量的数据。
set_cookie()方法的参数
属性 | 说明 |
---|---|
key | cookie的键(名称) |
value | cookie的值 |
max_age | cookie被保存的时间数,单位为秒。 |
expires | 具体的过期时间,一个datetime对象或UNIX时间戳 |
path | 限制cookie只在给定的路径可用,默认为整个域名下路径都可用 |
secure | 如果设为True,只有通过HTTPS才可以用 |
保存
通过response对象保存。
response = redirect(xxx)
response = render_template(xxx)
response = Response()
response = make_response()
response = jsonify()
通过对象调用方法
response.set_cookie(key,value,max_age,path)
其中max_age表示过期时间,单位是秒
也可以使用expires设置过期时间,expires=datetime.now()+timedelta(hour=1)
所有cookie都保存在客户端浏览器中,它会随着每一次的请求头部信息发送到服务器端,而且不止一个,所以想要接收这些cookie的数据内容,就必须依靠flask.request.coookies对象完成
获取
通过request对象获取。
request.form.get()
request.args.get()
cookie也在request对象中
request.cookies.get(key) ----> value
删除
通过response对象删除。 把浏览器中的key=value删除了
通过对象调用方法
response.delete_cookie(key)
session
session与cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie是存储在本地浏览器,session存储在服务器。存储在服务器的数据会更加的安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源
session常用方法
session: 是在服务器端进行用户信息的保存。一个字典
方法 | 说明 |
---|---|
get(K:_KT) | 根据指定的key获取数据 |
keys | 获取全部的key |
values | 获取全部的values |
items | 获取保存的全部项 |
pop(key,default=_misssing) | 弹出指定key的session数据 (弹出后删除) |
clear() | 删除session的内存空间和删除cookie |
update(name) | 更细指定session数据 |
注意:
使用session必须要设置配置文件,在settings.py配置文件中添加SECRET_KEY='xxxxx',
添加SECRET_KEY的目的就是用于sessionid的加密。如果不设置会报错。
保存
- 如果要使用session,需要直接导入:
from flask import session
把session当成字典使用,因此:session[key]=value
就会将key=value保存到session的内存空间
并会在响应的时候自动在response中自动添加有一个cookie:session=加密后的id
获取
用户请求页面的时候就会携带上次保存在客户端浏览器的cookie值,其中包含session=加密后的id
获取session值的话通过session直接获取,因为session是一个字典,就可以采用字典的方式获取即可。
value = session[key]
或者 value = session.get(key)
其实是如果使用session获取内容,底层会自动获取cookie中的sessionid值,进行查找并找到对应的session空间
删除
session.clear() 删除session的内存空间和删除cookie
del session[key] 只会删除session中的这个键值对,不会删除session空间和cookie
钩子函数
flask中具有四种钩子被做成了修饰器,我们在后端可以进行调用做相关的操作.
before_first_request
注册一个函数,在处理第一个请求之前运行.
@app.before_first_request
def bf_first_request():
print('before_first_request')
before_request
注册一个函数,在处理每次请求之前运行.
@app.before_request
def bf_request():
print('before_request')
after_request
注册一个函数,在每次请求之后运行.注册的函数至少需要含有一个参数,这个参数实际上为服务器的响应,且函数中需要返回这个响应参数
@app.after_request
def af_request(response):
return response
teardown_request
注册一个函数,同样在每次请求之后运行.注册的函数至少需要含有一个参数,这个参数实际上为服务器的响应,且函数中需要返回这个响应参数
@app.teardown_request
def td_request(response):
return response