第五章 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 : 用户中心科学与在线统计艺术 第五章:荣耀之钥:度量成功 我们的分析师常常得不到我们应得的喜欢,尊重和资金,因为我们没有充分地衡量一个黄金概念:成果.因为我们 ...
随机推荐
- Airflow怎么删除系统自带的DAG任务
点击这个按钮 找到dag文件所在路径,并进入路径将其文件删除即可
- 《Redis - 穿透/击穿/雪崩/集中失效》
一:什么是缓存穿透? - 定义 - 正常情况下,我们在理想的条件下去查询缓存数据都是存在的. - 那么请求去查询一条数据库中不存在的数据,也就是缓存和数据库都查询不到这条数据. - 所以请求每次都会打 ...
- Linux下安装redis 3.0及C语言中客户端实现demo
1.获取安装文件 wget http://download.redis.io/redis-stable.tar.gz 2.解压文件 tar xzvf redis-stable.tar.gz 3.进入目 ...
- element-ui 合并单元格的方法
arraySpanMethod({ row, column, rowIndex, columnIndex }) { // 只合并区域位置 //columnIndex 横的第一列 ...
- SAS学习笔记2 基础函数应用
输入输出语句(put和input函数) put()函数:把数值型或字符型变量转为字符型变量(输出变量) input()函数:将字符型变量转化为数值型变量(输入变量) 选择与删除语句(keep.drop ...
- MongoDB操作-备份和恢复
Mongodb数据库操作-备份 恢复 导出 导入 mongodb数据备份和恢复主要分为二种:一种是针对库的mongodump和mongorestore,一种是针对库中表的mongoexport和mon ...
- MySQL 解决source 命令导入数据库 乱码
在我把库.表.sql脚本的编码格式都设置为UTF-8后,任然有乱码,任然有报错: 于是按以下方式重新登录后,解决: mysql -u root -p --default-character-set=u ...
- Mysql对查询结果添加序列号
; as rownum,* from table1 :=和=的区别? "=",只有在set和update时才和:=一样,赋值的作用,其它都是等于的作用.鉴于此,用变量实现行号时,必 ...
- zblog2.X 连不上数据库原因
数据库配置Dim ZC_MSSQL_DATABASEZC_MSSQL_DATABASE="zb20" Dim ZC_MSSQL_USERNAMEZC_MSSQL_USERNAME= ...
- c#基础知识梳理(三)
上期回顾 - https://www.cnblogs.com/liu-jinxin/p/10824638.html 一.方法 一个方法是把一些相关的语句组织在一起,用来执行一个任务的语句块.每一个 C ...