* 指某些网站为了辨别用户身份、进行会话跟踪而储存在用户本地的数据(通常经过加密)。
* 复数形式Cookies。
* Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
* Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,
* 下次请求同一网站时就发送该Cookie给服务器.
* Cookie中的key/value可以由服务器端自己定义。
cookie的设置和获取
response.set_cookie(key,value,max_age)
request.cookies.get("key")
from flask import Flask, make_response, request
app = Flask(__name__)
#设置cookie
@app.route('/set_cookie')
def set_cookie():
#调用make_response方法获取响应体对象
response = make_response("set cookie")
#设置cookie
response.set_cookie("computer","lenovo")
response.set_cookie("age","13",10)
return response
解释: 服务器和用户来做状态保持的,里面存储的是敏感信息(比如身份证,登陆信息),由服务器设置,并存储在服务器(可以存在内存,文件,数据库等,最终解决方案是存在redis数据库中)
作用: 用来做用户的登陆状态保持
session的设置和获取
设置session:
sessioin[key] = value
获取session:
value = session.get(key)
注意点:
from flask import Flask, session
app = Flask(__name__)
#设置SECRET_KEY
app.config["SECRET_KEY"] = "tianwanggaidihu"
#设置session
@app.route('/set_session/' )
def set_session(name):
session["name"] = name
return "set session!"
#获取session
@app.route('/get_session')
def get_session():
value = session.get("name")
return "set session, name is %s"%value
if __name__ == '__main__':
app.run(debug=True)
在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等?
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session。
request
封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get(‘user’),获取的是get请求的参数。
session
用来记录请求会话中的信息,针对的是用户信息。举例:session[‘name’] = user.id,可以记录用户信息。还可以通过session.get(‘name’)获取用户信息。
它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
应用上下文对象有:current_app,g。
current_app
应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:
应用的启动脚本是哪个文件,启动时指定了哪些参数
加载了哪些配置文件,导入了哪些配置
连了哪个数据库
有哪些public的工具类、常量
应用跑再哪个机器上,IP多少,内存多大
g变量
g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别
g.name=‘abc’
注意:不同的请求,会有不同的全局变量
两者区别:
from flask import Flask, current_app
app = Flask(__name__)
@app.route('/')
def hello_world():
print(app.config.get("DEBUG"))
print(current_app.config.get("DEBUG"))
return "helloworld"
if __name__ == '__main__':
app.run(debug=True)
属于flask的扩展包,通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过:
python hello.py runserver -host ip地址
"""
- 解释: 属于flaks的扩展
- 作用: 用来动态运行程序,配合flask_migrate做数据库迁移
- 使用格式:
- 1.安装
- pip install flask_script
- 2.导入Manager类
- 3.创建对象manager,管理app
- 4.使用manager启动程序
- 启动命令: python xxx.py runserver -h(host是IP地址) -p(端口号) -d(调试模式)
"""
from flask import Flask
from flask_script import Manager
app = Flask(__name__)
app.config["DEBUG"] = True
#3.创建对象manager,管理app
manager = Manager(app)
@app.route('/')
def hello_world():
return "helloworld"
if __name__ == '__main__':
manager.run()
用来展示数据的html页面,这个过程也通常称为渲染,属于Jinja2的功能。 使用模板的好处:
Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名。
使用render_template函数封装模板引擎
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
response = render_template('file01template.html') # 需要用此函数关联模板文件
return response
if __name__ == '__main__':
app.run(debug=True)
<h1>整数:{ {number} }</h1>
<h1>元祖:{ {tuple[0]} }</h1>
<h1>列表:{ { list[0] } }</h1>
<h1>字典:{ { dict['key'] } }</h1>
模板语法的种类
分支格式:
{% if 条件 %}
语句1
{% else%}
语句2
{% endif %}
循环语句格式:
{% for 变量 in 容器 %}
{% endfor %}
注释:
{# 这里是注释的内容 #}
例:后端代码:
from flask import Flask, render_template
app = Flask(__name__)#默认省略了三个参数,static_url_path, static_folder, template_folders
@app.route('/')
def hello_world():
# 1.定义各种类型的变量
number = 10
str = "老王"
tuple = (1, 2, 3, 4, 5)
list = [6, 7, 8, 9, 10]
dict = {
"name": "bertwu",
"age": 29
}
# 2.携带变量到模板中展示
return render_template("file02.html", number=number, str=str, tuple=tuple, list=list, dict=dict)
if __name__ == '__main__':
app.run(debug=True)
jinjar2 模板代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div style="color:darkmagenta">
<h2>1.获取各种变量的值h2>
<h4>整数: {{number}}h4>
<h4>字符串: {{str}}h4>
<h4>元组: {{tuple}},分开获取: {{tuple[0]}}, {{ tuple.1 }}h4>
<h4>列表: {{list}},分开获取: {{ list[0] }}, {{ list.1 }}h4>
{# 如果字典使用方括号,获取,需要写成字符串,如果不是字符串,那么则会被当成变量对待 #}
<h4>字典: {{dict}}, 分开获取: {{ dict.name }}, {{ dict["age"] }}h4>
<h2>2.遍历元祖中的偶数h2>
{% for item in tuple %}
{% if item %2 == 0 %}
<h4>{{ item }}h4>
{% endif %}
{% endfor %}
<h2>3.遍历字典h2>
{% for key in dict %}
{# dict.key那么这个key会当成字典中的一个键, dict[key],那么这个key当成一个变量,很明显这里是一个变量 #}
<h4>{{ key }} = {{ dict[key] }}h4>
{% endfor %}
div>
body>
html>
过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。系统自带的过滤器分字符串过滤器和列表过滤器
{{ 字符串 | 字符串过滤器 }}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div style="background-color: olive">
{# 使用格式:{{ 字符串 | 字符串过滤器 }} #}
1.safe:禁用转义,让标签生效,负责会按照原标签输出
<p>{{ '<em>helloem>' | safe }}p>
2.capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello PYTHON' | capitalize }}p>
3.lower:把值转成小写
<p>{{ 'HELLO PYthON' | lower }}p>
4.upper:把值转成大写,中文没有大小写
<p>{{ 'hello python 你好' | upper }}p>
5.title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello world python java' | title }}p>
6.reverse:字符串反转
<p>{{ 'olleh' | reverse }}p>
<p>{{ '我爱你' | reverse }}p>
7.format:格式化输出
<p>{{ '%s is %d' | format('age',17) }}p>
8.striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>helloem>' | striptags }}p>
div>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div style="background-color: olive">
{# 使用格式:{{ 列表 | 列表过滤器 }} #}
1.first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}p>
2. last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}p>
3. length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}p>
4.sum:列表求和
<p>{{ [1,2,3] | sum }}p>
5.sort:列表排序,默认升序
<p>{{ [6,2,3,1,5,4] | sort }}p>
6.过滤器的链式调用
{# 过滤器的链式调用 #}
{{ "hello" | upper | reverse }}
div>
body>
html>
解释: 当系统提供的过滤器满足不了需求的时候,需要自定义
自定义过滤器有两种格式:
1.先定义好函数,再将函数添加到系统默认的过滤器列表中
app.add_template_filter(函数名,'过滤器名字')
2.定义函数的时候,直接使用系统过滤器进行装饰
@app.template_filter('过滤器名字')
def 函数名():
pass
案例:
1.获取列表偶数和
2.反转列表
from flask import Flask, render_template
app = Flask(__name__)
# 1.先定义好函数,再将函数添加到系统默认的过滤器列表中
def get_even_sum(list):
print(list)
sum = 0
for i in list:
if i % 2 == 0:
sum += i
return sum
# 参数1: 关联的函数名称, 参数2: 在模板中使用的过滤器名字
app.add_template_filter(get_even_sum, "even_sum")
# 2.定义函数的时候,直接使用系统过滤器进行装饰
@app.template_filter("reverse")
def listreverse(list):
list.reverse()
return list
@app.route('/')
def hello_world():
return render_template("file06custom_filter.html")
if __name__ == '__main__':
app.run(debug=True)
在模板中使用自定义过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>原列表: {{ [1,2,3,4,5,6] }}</h2>
<h2>偶数列表: {{ [1,2,3,4,5,6] | even_sum }}</h2>
<h2>反转列表: {{ [1,2,3,4,5,6] | reverse }}</h2>
<h2>降序列表: {{ [1,2,3,4,5,6,10,9,7] | sort | reverse }}</h2>
</body>
</html>
解释: 相当于python中的函数,定义好一段功能,在需要的时候进行调用即可
定义格式:
{% macro 宏名(参数) %}
{% endmacro %}
使用格式:
// 使用当前文件定义好的宏
{{ 宏名(参数) }}
//使用其他文件定义好的宏
{% import '文件' as 别名%}
{{ 别名.宏名(参数) }}
后端代码
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
return render_template("file07macro.html") # 关联宏文件
if __name__ == '__main__':
app.run(debug=True)
前端宏文件07
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{# 定义宏 #}
{% macro my_macro(name,password) %}
用户名: <input type="text" value="{{ name }}"><br>
密码: <input type="password" value="{{ password }}"><br>
{% endmacro %}
{# 调用当前文件宏 #}
{{ my_macro("bertwu","123") }}
{# 使用其他文件的宏 #}
{% import 'file08othermacro.html' as other %}
{{ other.my_input() }}
{{ other.my_div() }}
body>
html>
前端宏文件08,被07文件所引用
{% 定义自己的宏 %}
{% macro my_macro(name,password) %}
用户名: <input type="text" value="{{ name }}"><br>
密码: <input type="password" value="{{ password }}"><br>
{% endmacro %}
{% macro my_input() %}
<h1>这是一个其他文件的宏h1>
{% endmacro %}
{% macro my_div() %}
<div style="color: red;">我是一个孤独的divdiv>
{% endmacro %}
解释: 一个子模板继承自父模板
作用: 共性抽取,代码复用
父模板
子模板
注意点:
定义block的格式
{% block 名称 %}
{% endblock %}
父模板:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{# 头部部分 #}
{% block titleBlock %}
<h1>静夜思h1>
{% endblock %}
{# 正文部分 #}
{% block contentBlock %}
{% endblock %}
{# 底部部分 #}
<div>
<a href="#">点我有惊喜a>
div>
body>
html>
字模板1:
{% extends 'file11fu.html' %}
{# 重写正文部分 #}
{% block contentBlock %}
<p>
床前一锅汤,<br>
撒了一裤裆, <br>
抬头拿抹布, <br>
低头擦裤裆 <br>
p>
{% endblock %}
子模板2
{% extends 'file11fu.html' %}
{# 重写父类titleBlock内容 #}
{% block titleBlock %}
{{ super() }}
<h1>新静夜思h1>
{% endblock %}
{# 重写父类中的contentBlock内容 #}
{% block contentBlock %}
<p>
床前明月光,<br>
疑似地上霜, <br>
举头望明月, <br>
低头思故乡 <br>
p>
{% endblock %}
后端代码:
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
# return render_template("file10zi.html")
return render_template("file09zi.html")
if __name__ == '__main__':
app.run(debug=True)
解释: 在一个文件中完全拥有另外一个文件,不够灵活,没法扩展
格式:
方式一:
{% include '文件' %}
方式二:
{% include '文件' ignore missing %}
注意点: 后面加上 ignore missing, 如果包含的文件不存在,也不会报错,否则会报错。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
# 1.定义5条数据
my_list = [
{
"id": 1,
"value": "我爱工作"
},
{
"id": 2,
"value": "工作使人快乐"
},
{
"id": 3,
"value": "沉迷于工作无法自拔"
},
{
"id": 4,
"value": "日渐消瘦"
},
{
"id": 5,
"value": "以梦为马,越骑越傻"
}
]
# 2.在模板中显示4条
return render_template("file13practice.html", list=my_list)
if __name__ == '__main__':
app.run(debug=True)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<ul>
{# 如果dict.id 不等于5才遍历 #}
{% for dict in list if dict.id !=5 %}
{# 方式一 #}
{# {% if dict.id == 1 %}#}
{# <li style="background: yellow;"> {{ dict.value }} li>#}
{# {% elif dict.id == 2 %}#}
{# <li style="background: green;"> {{ dict.value }} li>#}
{# {% elif dict.id == 3 %}#}
{# <li style="background: red;"> {{ dict.value }} li>#}
{# {% else %}#}
{# <li style="background: purple;"> {{ dict.value }} li>#}
{# {% endif %}#}
{# 遍历的时候可以获取到从0开始的索引 #}
{# <h3>{{ loop.index0 }}h3>#}
{# 遍历的时候可以获取到从1开始的索引 #}
{# <h3>{{ loop.index }}h3>#}
{# 方式二 #}
{% if loop.index == 1 %}
<li style="background: yellow;"> {{ dict.value }} li>
{% elif loop.index == 2 %}
<li style="background: green;"> {{ dict.value }} li>
{% elif loop.index == 3 %}
<li style="background: red;"> {{ dict.value }} li>
{% else %}
<li style="background: purple;"> {{ dict.value }} li>
{% endif %}
{% endfor %}
ul>
body>
html>
from flask import Flask,render_template
app = Flask(__name__)
app.config["SECRET_KEY"] ="hahaha"
@app.route('/')
def hello_world():
return render_template("file14special_variable.html")
@app.route('/test/' )
def test(age):
return "test..."
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>config变量: {{ config }}</h2>
<h2>request: {{ request.method }}</h2>
<h2>request: {{ request.url }}</h2>
<h2>url_for(): {{ url_for("hello_world") }}</h2>
<h2>url_for(): {{ url_for("test",age=100) }}</h2>
</body>
</html>
from flask import Flask, render_template, flash
app = Flask(__name__)
app.config["SECRET_KEY"] = "fdjkfjdk"
@app.route('/')
def hello_world():
return render_template("file15flash.html")
@app.route('/test')
def test():
# 存储消息
flash("登陆成功")
return "test"
if __name__ == '__main__':
app.run(debug=True)
前端代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% 取flash中存的消息,无论存多少都一次性取出,只能取一次 %}
{{ get_flashed_messages() }}
body>
html>