第五章 Flask视图高级
add_url_rule和app.route原理剖析
add_url_rule
add_url_rule(rule,endpoint=None,view_func=None)
这个方法用来添加url与视图函数的映射。
如果没有填写endpoint,那么默认会使用view_func的名字作为endpoint,
有填写endpoint,使用endpoint指定的字符串作为view_func函数的别名。
在url_for调用时应使用endpoint传递的别名
@app.route('/',endpoint='index')
def hello_world():
# return 'Hello World!' + url_for('my_list')
return 'Hello World!'+url_for('alias')
def my_list():
return '我是列表页'
app.add_url_rule('/list/',endpoint='alias',view_func=my_list)
# app.test_request_context
# 请求上下文
with app.test_request_context():
print(url_for('index')) #结果是:/
if __name__ == '__main__':
app.run(debug=True)
add_url_rule相当于把/list/和my_list关联起来。endpioint相等于给视图函数命名一个别名。
def my_list():
return '我是列表页'
app.add_url_rule('/list/',endpoint='alias',view_func=my_list)
#和下面的等价:
@app.route('/list/',endpoint='alias')
def my_list():
return '我是列表页'

app.route原理
@app.route('/')装饰器底层是使用add_url_rule来实现url与视图函数映射的,

标准类视图及其使用场景
标准视图继承自flask.views.View,并且在子类中必须实现dispatch_request方法,这个方法类似于视图函数,也要返回一个基于Response或者其子类的对象。
- 标准类视图,必须继承自flask.views.View.
- 必须实现dipatch_request方法,当请求过来后会执行该方法且方法的返回值和之前的函数视图返回值一样,必须返回Response或者子类的对象,或者是字符串,或者是元组。
- 必须通过app.add_url_rule(rule,endpoint,view_func)来做url与视图的映射。view_func这个参数,需要使用类视图下的as_view类方法类转换:ListView.as_view('list')。
- 如果指定了endpoint,那么在使用url_for反转的时候就必须使用endpoint指定的别名。如果没有指定endpoint,那么就可以使用as_view(视图名字)中指定的视图名字来作为反转。
- 类视图有以下好处:可以继承,把一些共性的东西抽取出来放到父视图中,子视图直接拿来用。但是也不是说所有的视图都要使用类视图,这个要根据情况而定。
# 有几个url需要返回json数据
# 有几个视图,是需要返回相同的变量 class JSONView(views.View):
def get_data(self):
raise NotImplementedError def dispatch_request(self):
return jsonify(self.get_data()) class ListView(JSONView):
def get_data(self):
return {"username":'wqbin','password':''} app.add_url_rule('/list/',endpoint='my_list',view_func=ListView.as_view("list"))

class ADSView(views.View):
def __init__(self):
super(ADSView, self).__init__()
self.context = {
'ads': '这里是wqbin的博客'
} class LoginView(ADSView):
def dispatch_request(self):
self.context.update({
'username': 'wqbin'
})
return render_template('login.html',**self.context) class RegistView(ADSView):
def dispatch_request(self):
return render_template('regist.html',**self.context) app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
app.add_url_rule('/regist/',view_func=RegistView.as_view('regist'))


基于调度方法的类视图
基于请求方法的类视图:
基于方法的类视图,是根据请求的method来执行不同的方法的。

如果用户是发送的get请求,那么将会执行这个类的get方法。如果用户发送的是post请求,那么将会执行这个类的post方法。其他的method类似,比如delete、put。
这种方式,可以让代码更加简洁。
所有和get请求相关的代码都放在get方法中,所有和post请求相关的代码都放在post方法中。就不需要跟之前的函数一样,通过request.method == 'GET'。
class LoginView(views.MethodView):
def __render(self,error=None):
return render_template('login.html',error=error) def get(self):
return self.__render() def post(self):
username = request.form.get('username')
password = request.form.get('password')
if username == 'wqbin' and password == '':
return '登录成功'
else:
return self.__render(error='用户名或密码错误') app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
<table>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="立即登录"></td>
</tr>
</tbody>
</table>
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
</form>
</body>
</html>
html
类视图中使用装饰器
- 如果使用的是函数视图,那么自定义的装饰器必须放在`app.route`下面
- 类视图的装饰器,需要重写类视图的一个类属性`decorators`,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。
def login_required(func):
@wraps(func)
def wrapper(*args,**kwargs):
username = request.args.get('username')
if username and username == 'wqbin':
return func(*args,**kwargs)
else:
return '请先登录'
return wrapper @app.route('/settings/')
@login_required
def settings():
return '这是设置界面' class ProfileView(views.View):
decorators = [login_required]
def dispatch_request(self):
return '这是个人中心界面' app.add_url_rule('/profile/',view_func=ProfileView.as_view('profile'))

蓝图的基本使用
1. 蓝图的作用
让我们的Flask项目更加模块化,结构更加清晰。
可以将相同模块的视图函数放在同一个蓝图下,同一个文件中,方便管理。
2. 基本语法:
* 在蓝图文件中导入Blueprint:
from flask import Blueprint
user_bp = Blueprint('user',__name__)
我们仔细了解Blueprint类的构造函数:
def __init__(self, name, import_name, static_folder=None,
static_url_path=None, template_folder=None,
url_prefix=None, subdomain=None, url_defaults=None,
root_path=None):
_PackageBoundObject.__init__(self, import_name, template_folder,
root_path=root_path)
self.name = name
self.url_prefix = url_prefix
self.subdomain = subdomain
self.static_folder = static_folder
self.static_url_path = static_url_path
self.deferred_functions = []
if url_defaults is None:
url_defaults = {}
self.url_values_defaults = url_defau
__init__.py
* 在主app文件中注册蓝图:
from blueprints.user import user_bp
app.regist_blueprint(user_bp)
3. 如果想要某个蓝图下的所有url都有一个url前缀,那么可以在定义蓝图的时候,指定url_prefix参数:
user_bp = Blueprint('user',__name__,url_prefix='/user/')
在定义url_prefix的时候,要注意后面的斜杠,如果给了,那么以后在定义url与视图函数的时候,就不要再在url前面加斜杠了。
4. 蓝图模版文件的查找:
* 如果项目中的templates文件夹中有相应的模版文件,就直接使用了。
* 如果项目中的templates文件夹中没有相应的模版文件,那么就到在定义蓝图的时候指定的路径中寻找。并且蓝图中指定的路径可以为相对路径,相对的是当前这个蓝图文件所在的目录。比如:
news_bp = Blueprint('news',__name__,url_prefix='/news',template_folder='bp_template')
因为这个蓝图文件是在blueprints/news.py,那么就会到blueprints这个文件夹下的bp_template文件夹中寻找模版文件。
5. 蓝图中静态文件的查找规则:
* 在模版文件中,加载静态文件,如果使用url_for('static'),那么就只会在app指定的静态文件夹目录下查找静态文件。
* 如果在加载静态文件的时候,指定的蓝图的名字,比如`news.static`,那么就会到这个蓝图指定的static_folder下查找静态文件。
<link rel="stylesheet" href="{{ url_for('static',filename='news_list.css') }}">
<link rel="stylesheet" href="{{ url_for('newsbp.static',filename='news_list.css') }}">
6. url_for反转蓝图中的视图函数为url:
* 如果使用蓝图,那么以后想要使用url_for反转蓝图中的视图函数为url,那么就应该在使用url_for的时候指定这个蓝图,比如`newsbp.news_list`。否则就找不到这个endpoint。在模版中的url_for同样也是要满足这个条件,就是指定蓝图的名字。
* 即使在同一个蓝图中反转视图函数,也要指定蓝图的名字。
@app.route('/')
def hello_world():
print(url_for('newsbp.news_list'))
return render_template('index.html')
子域名实现详解
蓝图实现子域名:
1. 使用蓝图技术。
2. 在创建蓝图对象的时候,需要传递一个subdomain参数,来指定这个子域名的前缀。例如:cms_bp = Blueprint('cmsbp',__name__,subdomain='cms')。
from flask import Blueprint
cms_bp = Blueprint('cmsbp',__name__,subdomain='cms')
@cms_bp.route('/')
def index():
return 'cms index page'
3. 需要在主app文件中,需要配置app.config的SERVER_NAME参数。例如:
app.config['SERVER_NAME'] = 'jd.com:5000'
- ip地址不能有子域名。
- localhost也不能有子域名。
4. 在C:\Windows\System32\drivers\etc下,找到hosts文件,然后添加域名与本机的映射。例如:
127.0.0.1 jd.com
127.0.0.1 cms.jd.com
域名和子域名都需要做映射。
第五章 Flask视图高级的更多相关文章
- mariadb(第五章)视图、事物、索引、外键
视图 对于复杂的查询,在多个地方被使用,如果需求发生了改变,需要更改sql语句,则需要在多个地方进行修改,维护起来非常麻烦 假如因为某种需求,需要将user拆房表usera和表userb,该两张表的结 ...
- 第五章:深入Python的dict和set
第五章:深入Python的dict和set 课程:Python3高级核心技术 5.1 dict的abc继承关系 class Mapping(Collection): __slots__ = () &q ...
- 读JS高级——第五章-引用类型 _记录
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 第五章 MySQL事务,视图,索引,备份和恢复
第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...
- 【Flask】视图高级
# 视图高级笔记:### `add_url_rule(rule,endpoint=None,view_func=None)`这个方法用来添加url与视图函数的映射.如果没有填写`endpoint`,那 ...
- flask之三:视图高级
视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule('/list/',endpoint='myweb',view_fun ...
- C#高级编程 (第六版) 学习 第五章:数组
第五章 数组 1,简单数组 声明:int[] myArray; 初始化:myArray = new int[4]; 为数组分配内存. 还可以用如下的方法: int[] myArray = new in ...
- 《Entity Framework 6 Recipes》中文翻译系列 (22) -----第五章 加载实体和导航属性之延迟加载
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第五章 加载实体和导航属性 实体框架提供了非常棒的建模环境,它允许开发人员可视化地使 ...
- 精通Web Analytics 2.0 (7) 第五章:荣耀之钥:度量成功
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第五章:荣耀之钥:度量成功 我们的分析师常常得不到我们应得的喜欢,尊重和资金,因为我们没有充分地衡量一个黄金概念:成果.因为我们 ...
随机推荐
- [转帖]为何 CPU 只用硅,而不用能耗更低的锗制作?知乎好文章
作者:鲁超链接:https://www.zhihu.com/question/28935966/answer/617701106来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- JAVA MAC 比较大小
2个MAC String mac_1="AAAAAAAAAAAA"; String mac_1="AAAAAAAAAAAB"; 方法一: int a = 0; ...
- Turn.js 实现翻书效果(自适应单双页)
来源:https://www.cnblogs.com/hellman/p/10683492.html在上面的来源基础上增加页码显示,自适应单双页PC端效果: 移动端展示: 源码下载地址:http:// ...
- dict字典
dict字典 字典的概述 • 概述:使⽤键-值(key-value)⽅式存储. • key的特点: • 1.字典中的key必须是唯⼀的 • 2.key值必须是不可变的数据类型:字符串.元组.Numbe ...
- 机器学习-svd实现人脸识别
加载sklearn中的人脸数据集 from sklearn.datasets import fetch_lfw_people faces = fetch_lfw_people() 执行上面的第二行程序 ...
- diy操作系统 附录:常用命令
ld -m elf_i386 as --32 gcc -m 16 o
- Python中下划线的5种含义
目录 单前导下划线 _var 当涉及到变量和方法名称时,单个下划线前缀有一个约定俗成的含义. 它是对程序员的一个提示 - 意味着Python社区一致认为它应该是什么意思,但程序的行为不受影响. 单末尾 ...
- Intergalaxy Trips CodeForces - 605E (期望,dijkstra)
大意: 给定矩阵$p$, $p_{i,j}$表示每一秒点$i$到点$j$有一条边的概率, 每秒钟可以走一条边, 或者停留在原地, 求最优决策下从$1$到$n$的期望用时. $f_x$为从$x$到$n$ ...
- (四)lucene之文本域加权
一.前言 1.1 应用场景 有时在搜索的时候,会根据需要的不同,对不同的关键值或者不同的关键索引分配不同的权值,让权值高的内容更容易被用户搜索出来,而且排在前面. 为索引域添加权是再创建索引之前,把索 ...
- (九)springmvc之json的处理(服务端发送json数据到客户端)
一.json处理方法有两种 1:导入Spring需要json的jar包.(本例使用) 使用@ResponseBody该注解用于将Controller的方法返回的对象,通过HttpMessageConv ...