钩子函数
from flask import Flask
app = Flask(__name__)
# 第一次请求之前会来调用
# 初始化操作
@app.before_first_request
def demo1():
print("第一次请求会调用"")
# 每次请求之前都会调用,应用场景:封装ip处理
@app.before_request
def demo2():
print("每次请求之前会被调用")
#每次请求之后都会调用这个钩子函数,应用场景:对response进行统一处理
@app.after_request
def demo3(response):
# response.headers["Content-Type"] = "application/json"
print("每次请求之后才会调用")
return response
# 每次都会执行,都会带入一个服务器的错误过来
@app.teardown_request
def demo4(err):
print(err)
print("每次请求之后都会调用一个服务器错误过来)
if __name__ == "_main__":
app.run(debug=True)
对cookie进行操作:
from flask import Flask, make_response, request
app = Flask(__name__)
@app.route("/login")
def login():
"""登录成功之后借助cookie保存用户登录信息"""
# 创建响应对象
response = make_response("login_success")
# 借助响应对象的set_cookie方法设置键值对
# 参数1:ke, 参数2:value, 参数3:max_age表示过期时长(以秒为单位)
# set_cookie("key",值) Cookie是存储在浏览器中的一段纯文本
response.set_cookie("user_name", "kangkang", max_age=3600)
response.set_cookie("age", "18", max_age= 3600)
return response
# 获取cookie
@app.route("/index")
def index():
"""再次请求首页的时候,提起cookie中的用户信息"""
user_name = request.cookies.get("user_name", "")
age = request.cookies.get("age", "")
return "index %s --- %s" %(user_name, age)
# 删除cookie
@app.route("/login_out")
def login_out():
response = make_response("login_out success")
response.delete_cookie("user_name")
response.delete_cookie("age")
#将响应对象返回
return response
if __name__== "__main__":
app.run(debug=True)
对session进行操作,session依赖于cookie,服务器会返回一个session_id即为cookie,session里面包含用户信息
from flask import Flask, session
app = Flask(__name__)
# session需要设置秘钥,可以写一个任意的字符串,两种写法,app.config是个字典
app.config="2323242423"
app.config["SECREY_KEY"] = "3213232"
@app.route("/login")
def login():
# session将用户数据存储在服务器的内存中--redis数据库
session["user_name"]= "kangkang"
session["user_id"] = "12"
return "login success"
@app.route("/index")
def index():
user_name = session.get("user_name", "")
user_id = session.get("user_id", "")
return "index:%s ---%s" %(user_name, user_id)
@app.route("/login_out")
def login_out():
session.pop("user_name", "")
session.pop("age", "")
return "login_out success"
if __name__ == "__main__":
app.run(debug=True)
捕获异常:
from flask import Flask, redirect, abort
app = Flask(__name__)
@app.route("/")
def hello():
a = 1/0
abort(404) # 主动产生一个404异常,abort需要先导入该库,abort传入的必须是http存在的错误状态码
return "hello world"
# 通过errorhandler捕获错误状态码
@app.errorhandler(404)
def handler(e):
print(e)
# 重定向到百度的错误页面链接
return redirect("https://www.baidu.com/search/error.html")
# 通过errorhandler捕获异常
@app.errorhandler(ZeroDivisionError)
def err(err):
return "不能除以0"
if __name__ == "__main__":
app.run(debug=True)
上下文:
请求上下文: request和session
应用上下文:current_app, g变量(flask程序全局的一个临时变量)
from flask import Flask, request, session, current_app, g
app =Flask(__name__)
app.config["SECRECT_KEY"] = "avdvdvd"
# print(request.method) Working outside of request context.请求上下文超出范围
# print(g.user) Working outside of request context.应用上下文超出范围
# 只能在视图函数里面进行操作,在外部进行操作就会超出范围
@app.route("/")
def hello():
# 请求上下文
print(request.method)
print(request.url)
session["user_name"] = "curry"
print(session.get("user_name", ""))
# 应用上下文(current_app, g)
print(current_app.config.get("DEBUG"))
g.user = "james"
print(g.user)
return "hello world"
if __name__ == "__main__":
app.run(debug=True)
- 请求上下文:保存了客户端和服务器交互的数据
- 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等
Flask-Script拓展
需要安装Flask-Script拓展
pip install flask-script
from flask import Flask
from flask_script import Manager
app = Flask(__name__)
manager= Manager(app)
@app.route("/")
def hello():
return "hello world"
if __name__ == "__main__":
manager.run()
通过终端命令: python XX.py runserver -h ip地址 -p 端口号 -d
同样也可以配置该文件的环境变量进行右键运行.
Jinja2模板引擎简介
视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。本节学到的模板,它的作用即是承担视图函数的另一个作用,即返回响应内容。
- 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
- 使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”
- Flask是使用 Jinja2 这个模板引擎来渲染模板
使用模板的好处:
视图函数只负责业务逻辑和数据处理(业务逻辑方面)
而模板则取到视图函数的数据结果进行展示(视图展示方面)
代码结构清晰,耦合度低
Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名
Flask提供的 render_template 函数封装了该模板引擎
render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值
{{}}来表示变量名,这种{{}}语法叫做代码块变量, {{{position.title}}
Jinja2模板中的变量代码块可以是任意Python类型或者对象,只要它能够Python的Str()方法转换为一个字符串就可以,
{{your_dict['key']}}
{{your_list[0]}}
用{% %}定义的控制代码块,可以实现一些语言层次的功能,比如循环或if语句
{% if user %}
{{user}}
{% else %}
hello!
<ul>
{% for index in indexs %}
<li>{{index}}</li>
{% endfor %}
</ul>
使用{# #}进行注释,注释的内容不会再html中被渲染出来
模板的基本使用:
在项目下创建templates文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
myint = 18
mystr = "curry"
my_list =[1, 23,4,6,5]
my_dict = {
"name":"duan",
"age":28
}
return render_template("dem01.html",
myint = myint, mystr = mystr, my_dict=my_dict, my_list = my_liust)
if __name == "__main__":
app.run()
对应的demo01.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我的模板html内容
<br/>{{ my_str }}
<br/>{{ my_int }}
<br/>{{ my_array }}
<br/>{{ my_dict }}
</body>
</html>
链式调用: {{"hello world" | reverse | upper}}
常见内建过滤器:
字符串操作
safe:禁止转义 {{"<em>hello</em>"| safe}}
capitalize:把变量的首字母转成大写,其余字母小写 {{'hello" | capitalize}}
lower:把值转成小写, {{"HELLO" | lower}}
upper:把值转成大写,{{"hello" | upper}}
title:把每个单词的首字母都转成大写, {{'he is girl" | title}}
reverse:字符串反转,
format:格式化输出 {{'%s is %d' | format('name', 7)}}
striptags:把html中的tag去掉, {{'<h1>hello</h1>" | striptags}}
truncate:字符串截断 {{'hello every one" | truncate(9) }}
列表操作
list=[1,2,3,1,2,3,6,8,4]
first :取第一个元素 {{list | first}}
last:取最后一个元素{{list | last}}
length:获取列表长度{{list | length}}
sum:求列表的和{{list | sum}}
sort:列表排序 {{list | sort}}
语句块过滤:
{% filter upper %}
# 一大堆文字#
{% endfilter %}
自定义过滤函器
from flask import render_template, Flask
app = Flask(__name__)
# 方法一:自定义列表反函数
@app.template_filter("list_reverse")
def list_rever(list):
list.reverse()
return list
# 方式二:将自定义的函数添加到flask过滤器中,add_template_filter(函数名, "创建过滤器名称") 函数名不需要打引号
app.add_template_filter(list_rever, "list_reverse")
@app.route("/")
def index():
list = [1,2,3,4,6,5]
return render_template("demo02.html", list = list)
if __name__ == "__main__":
app.run(debug=True)
demo02.html内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
自定义过滤器<hr>
<body>
{{ list }}
<br>
{{ list | list_reverse }}
</body>
</html>
控制代码:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
# 只显示四行数据, 并设置颜色
my_list = [
{
"id":1,
"value":"我爱代码"
},
{
"id": 2,
"value": "代码使人快乐"
},
{
"id": 3,
"value": "沉迷于代码无法自拔"
},
{
"id": 4,
"value": "日渐消瘦"
},
{
"id": 5,
"value": "以梦为马,越骑越傻"
}
]
return render_template("demo03.html", my_list = my_list)
if __name__ == "__main__":
app.run(debug=True)
demo03.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
控制代码块<hr>
{% for item in my_list%}
{# {% if item.id != 5 %}#}
{% if loop.index == 1 %}
<li style="background-color: yellow">{{ item.value }}</li>
{% elif loop.index == 2%}
<li style="background-color: #2aabd2">{{ item.value }}</li>
{% elif loop.index == 3 %}
<li style="background-color: #2b542c">{{ item.value }}</li>
{% elif loop.index == 4 %}
<li style="background-color: #8a6d3b">{{ item.value }}</li>
{% elif loop.index == 5 %}
<li style="background-color: darkgrey">{{ item.value }}</li>
{% endif %}
{# {% endif %}#}
{% endfor %}
loop.index: 当前循环迭次的次数(从1开始)
loop.index0:当前循环迭代的次数(从0开始)
loop.revindex: 到循环结束需要迭的次数(从1开始)
loop.revindex0:到循环结束需要迭代的次数(从0开始)
loop.first 第一迭代,为True
loop.last 最后一次迭代,为True
loop.length 序列中的项目数
loop.cycle:在一串序列期间取值的辅助函数.
模板继承:
在模板中,可能会遇到以下情况:
- 多个模板具有完全相同的顶部和底部内容
- 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
- 多个模板中具有完全相同的 html 代码块内容
像遇到这种情况,可以使用 JinJa2 模板中的 继承 来进行实现
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/parent")
def parent():
return render_template("base.html")
@app.route("/child")
def child():
return render_template("child.html")
if __name__ == "__main__":
app.run(debug=True)
base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
{# 把要重写的父类的内容用{% block 名称x %} XXX {% endblock %}#}
{% block testA %}
<h2>父类模板<h2>
{% endblock %}
<h2>父类内容</h2>
<h2>父类底部</h2>
<body>
</body>
</html>
child.html内容:
{# 子类继承父类使用extends关键字 {% extends '父类.html' %}#}
{% extends "base.html'' %}
{# 重写父类中的部分内容#}
{# 不丢失父类原有的内容使用super()#}
{% block testA % }
{{super()}}
<h2>我是子类模板</h2>
{% endblock %}
怎样设置templates的html文件在使用render_template方法时自动弹出里面的html文件进行选择
选择Jinja2,apply之后点击ok即可
可以设置自己设置状态码及状态码解释
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
# 666代表状态码, 解释为状态码的解释信息
return "hello world", "666 解释"
if __name__ == "__main__":
app.run(debug=True)