视图是一个应用对请求进行响应的函数。 Flask 通过模型把进来的请求 URL 匹配到 对应的处理视图。视图返回数据, Flask 把数据变成出去的响应。 Flask 也可以反 过来,根据视图的名称和参数生成 URL 。
返回值:其实返回值返回的都是一个响应对象,底层将返回的字符串包装成一个response对象。其实就是底层的Response父类的default-minetype设置成text/html类型,用户看到的就是网页内容。

视图函数的返回值会自动转换为一个响应对象。如果返回值是一个字符串,那么会被转换为一个包含作为响应体的字符串、一个 200 OK 的状态代码 和一个 text/html 类型的响应对象(response对象)。返回值的类型其实不只仅仅有字符串类型,还支持返回字典,元组,响应对象,WSGI回调函数(# The return type must be a string, dict, tuple, Response instance, or WSGI callable)。
如果视图返回的是一个响应对象,那么就直接返回它。
如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的 响应对象。
如果返回的是一个字典dict,那么它会被转换为一个 JSON 响应。
如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项目,且项目应当由 (response, status) 、 (response, headers) 或者 (response, status, headers) 组成。 status 的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典。
如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。
如果想要在视图内部掌控响应对象的结果,也就是响应头的信息不满足你的需求,需要在响应头中添加额外的信息,或者想要返回一个字符串页面内容,那么可以使用 make_response() 函数。

假设有如下视图:
@app.errorhandler(404)
def not_found(error):
return render_template('error.html'), 404
可以使用 make_response() 包裹返回表达式,获得响应对象,并对该对象 进行修改,然后再返回:
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return resp
@app.route('/index4')
def index4():
content = '''
首页
欢迎来到京东购物网站
- hello
- abc
- world
'''
response = make_response(content) # 返回值就是一个response对象
# 定制响应头
response.headers['mytest'] = '123abc'
response.headers['myhello'] = 'hellohello'
# 将定制好的response返回
return response
总结:
(1)什么时候需要使用make_response?
当返回一个视图的时候,需要定制响应头,则可以使用make_response()包裹相应信息。
(2)response对象常用的属性与方法:
print(response.content_type)
print(response.headers)
print(response.status_code) # 200
print(response.status) # 200 OK
(3)视图函数的返回值,response响应:
只需要导入,通过from flask import request,导入之后可以获取对象的属性和方法。
属性:
print(request.headers) # request对象 对象访问属性,也可以调用方法
print(request.path)
print(request.full_path)
# 获取到提交的参数内容,例如get形式提交表单
# /register2?username=zhangsan&address=Beijing
print(request.base_url)
print(request.url)
跟请求方法相关的: 获取页面提交的内容
(1)get:
request.args 底层是字典的形式 主要获取get提交的请求参数
如果是get请求格式是这个样子的:/register2?username=zhangsan&address=Beijing
此时的username是form表单中表单元素的name值
print(request.args) # dict类型 d = {'a':'aaa','b':'7878'} d.get('b') 只能取到get请求的
print(request.args.get('username')) # 获取值
print(request.args.get('address'))
(2)post:
request.form 底层是字典的形式 主要获取post提交的请求参数
注意post提交必须在路由中进行设置,通过methods = [‘GET’,‘POST’]
按照此种形式:
@app.route('/register2', methods=['GET', 'POST'])
def register2(): # 获取页面提交的内容
....... 内容省略
获取数据:
print(request.form) # 如果请求方法是post,则需要通过request.form取值
print(request.form.get('username'))
print(request.form.get('address'))
如果想在视图函数中获取模板xxx.html的内容则通过render_template()
render_template(‘模板名称’) 返回值是一个字符串,主要是通过模板引擎(Jinjia2)去找到文件并将模板内容转成字符串的形式。

@app.route('/register')
def register():
return render_template('register.html') # 默认去模板文件夹中找模板文件。
疑问:怎么知道哪个文件时模板文件夹?
答:创建Flask对象的时候,有一个template_folder参数设置成了template,声明好了模板文件夹,就回去这里指定的文件里面找模板文件了。
redirect(‘/’)实现重定向,两次响应。但是如果在项目中,会有很多路径或者路径比较长,不易记,所以可以使用url_for来指定endpoint(在路由的装饰器上添加endpoint),去访问真正的路径。
url_for有两种使用方式:
@app.route('/', endpoint='index')
def index():
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
print(request.method)
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
repassword = request.form.get('repassword')
# 用户密码一致性验证
if password == repassword:
# 保存用户
user = {'username': username, 'password': password}
users.append(user)
return redirect(url_for('index')) # 有两次响应:1。302状态码 + location 2。 返回location请求地址内容
else:
return '两次密码不一致'
return render_template('register.html')
@app.route('/show')
def show():
# users[] ----> str'' json字符串
j_str = json.dumps(users)
return j_str
@app.route('/test')
def test():
url = url_for('index') # 路径反向解析
print(url) # /
return 'test'
如果需要传值到模板页面中,渲染在页面上显示的话,可以在视图函数中返回的时候添加参数,例如:return render_template(‘show_1.html’, girls=girls, users=users)
(1)在模板中获取view中传递的变量值:{{ 变量名}},类似于vue中使用mastache语法,也叫双大括号语法显示变量值。变量值支持字符串、列表、元组、set、对象等常用的数据类型
render_template(‘模板名字’,key=value,key=value)
@app.route('/show')
def show():
name = 'xzz' # str
age = 18 # int
friends = ['迪丽热巴', 'cr', '任嘉伦'] # list
dict1 = {'gift': 'YSL', 'gift1': '鲜花', 'gift2': '包包'} # dict
# 创建对象
girlfriend = Girl('cr', 'mz') # 自定义的类构建的类型:Girl对象
return render_template('show.html', name=name, age=age, gender='男', friends=friends, dict1=dict1, girl=girlfriend)
模板文件显示内容:
用户信息展示
用户名是:{{ name }} -- {{ age }} ---{{ gender }}
{{ friends.0 }}
{{ dict1.get('gift') }} --- {{ dict1.gift1 }}
{{ girl.gender }} -- {{ girl.name }} -- {{ girl.addr }}

模板文件获取值的一些简化写法:
{{ list.0 }} 同 {{ list[0] }}
{{ dict.key }} 同 {{ dict.get(key) }}
{{ girl.name }} 同 {{ 对象.属性 }}
(2)控制块:
if语句
{% if 条件 %}
{% endif %}
{% if 条件 %}
条件为True
{% else %}
条件为False
{% endif %}
{% for girl in girls %}
{# |相当于过滤器 #}
{% if girl|length >= 3 %}
- {{ girl }}
{% else %}
- {{ girl }}
{% endif %}
{% endfor %}

for语句
{% for 变量 in 可迭代的对象 %}
for循环要做的任务
{% endfor %}
for循环还有一个loop变量,通过该变量可以获取到数据的下标(序号):
loop.index 序号从1开始
loop.index0 序号从0开始
loop.revindex reverse 序号是倒着的
loop.revindex0
loop.first 布尔类型 是否是第一行
loop.last 布尔类型 是否是第二行
{% for user in users %}
{{ loop.index }}
{{ user.username }}
{{ user.password }}
{{ user.addr }}
{{ user.phone }}
{% endfor %}

过滤器的本质就是函数,模板语法中过滤器:
{{ 变量名 | 过滤器(*args) }}
{{ 变量名 | 过滤器 }}
(1)常见的过滤器:
1.safe : 禁用转译
msg = '520快乐!
'
return render_template('show_2.html', girls=girls, users=users, msg=msg)
不想让其转译:
{{ msg | safe }}
2.capitalize:单词的首字母大写
{{ n1 | capitalize }}
3.lower和upper
大小写的转换
4.title 一句话中每个单词的首字母大写
msg = 'She is a beautiful girl'
{{ msg | title}}
5.reverse 翻转
{{ n1 | reverse}}
6.format
{{ '%s is %d years old' | format('cr',18) }}
7.truncate 字符串截断
(2)list的操作:
{# 列表过滤器的使用 #}
{{ girls | first }}
{{ girls | last }}
{{ girls | length }}
{#{{ girls | sum }} 整型的计算 #}
{{ [1,3,5,7,9] | sum }}
{{ [1,8,5,7,3] | sort }}
(3)dict
{% for v in users.0.values() %} ---->获取值
{{ v }}
{% endfor %}
{% for k in users.0.keys() %} ----》获取键
{{ k }}
{% endfor %}
{% for k,v in users.0.items() %} ---》获取键值
{{ k }}---{{ v }}
{% endfor %}
(4)自定义过滤器:
(1)模板继承
需要模版继承的情况:
模板复用标签:
{% block 名字 %}
{% endblock %}
实现步骤:
父模板:
子使用父模板:
#如果需要引入外部文件,比如说引入样式文件,脚本文件等公共的文件。url_for默认只有一个参数,就是static,filename是关键字参数,必须要加上filename关键字才能成功访问。
include: 包含,在A,B,C页面都共同的部分,但是其他页面没有这部分,这个时候考虑使用include。
步骤:
(1)把它看作是jinja2的一个函数,这个函数可以返回一个HTML字符串
(2)目的:代码可以复用,避免代码冗余
定义两种方式:
{# 定义宏 #}
{% macro form(action,value='登录',method='post') %}
{% endmacro %}
{# 调用宏 #}
{{ form('/') }}
# 将需要复用的宏单独放到一个文件中,哪里需要就导入调用即可。
{% macro form(action,value='登录',method='post') %}
{% endmacro %}
# 在其他文件中使用
{% import 'macro/macro.html' as func %}
{{ func.form('/welcome',value='注册') }}
(1)变量: {{ 变量 }}
(2)块:
成对出现
{% if 条件 %} …{% endif %}
{% for 条件 %} …{% endfor %}
{% block 条件 %} …{% endblock %}
{% macro 函数声明 %} 函数体 {% endmacro %}
单个出现
{% include ‘’ %} 包含
{% import ‘’ %} 导入宏
{% extends ‘’ %}
函数/宏使用
{{ url_for(‘static’,filename=‘’) }}
{{ hongname(xxx) }}