flask之三:视图高级
视图高级
app.route
和app.add_url_rule
app.add_url_rule
app.add_url_rule('/list/',endpoint='myweb',view_func=my_list)
这个方法是用来添加url
与视图函数
的映射。如果没有填写endpoint
那么会默认使用view_func
的名字来作为endpoint
。
因此在使用url_for
的时候,就要看在映射的时候有没有传递endpoint
参数,如果传递了,那么就使用endpoint
指定的字符串。
付过没有使用的话就使用view_func
定义的名字。
app.route(rule,**options)
装饰器
这个装饰器的底层就是用add_url_rule
来实现url与视图函数映射的。
- 小例子如下:
from flask import Flask,url_for
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True
})
@app.route('/',endpoint='index')
def hello_world():
print(url_for('myweb'))
return 'Hello World!'
def my_list():
return 'list page!'
app.add_url_rule('/list/',endpoint='myweb',view_func=my_list)
#请求上下文的定义,结合url_for
with app.test_request_context():
print(url_for('index'))
if __name__ == '__main__':
app.run()
类视图
之前我们接触的视图都是函数,所以一般简称视图函数。
其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,
写完类视图还需要通过app.add_url_rule(url_rule,view_func)
来进行注册。以下将对两种类视图进行讲解
标准视图
- 标准类视图必须继承自
flask.views.View
- 必须实现
dispatch_request
方法,以后请求过来以后,会执行这个方法。这个方法的返回值就相当于是之前的函数视图一样,也必须返回Request
或者子类的对象(字符串或者元组)。 - 必须是通过
app.add_url_rule(rule,endpoint,view_func)
来做url映射。
view_func
这个参数,要使用as_view
这个方法来转换
- 如果指定了
endpoint
,那么在使用url_for
反转的时候,就要使用endpoint
指定的那个值,如果没有指定那个值,就使用as_view
中指定的视图名字来作为反转。 - 类视图有以下的好处,可以将一些共性的东西抽取出来放到父视图中,子视图直接继承就可以了,但是也不是说所有的视图都要使用类视图,这个要根据实际情况来定。
- 小例子:
from flask import Flask,views,url_for
app = Flask(__name__)
class ListView(views.View):
def dispatch_request(self):
return 'list view'
#app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
app.add_url_rule('/list/',view_func=ListView.as_view('list'))
with app.test_request_context():
print(url_for('list'))
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
- 类视图的小例子:
from flask import Flask,url_for,views,jsonify,render_template
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True
})
#自定义封装,返回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':'wanghui',
'password':123456,
}
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':"今年过节不收礼,收礼只收脑白金"
}
class RegistView(ADSView):
def dispatch_request(self):
self.context.update({'username':'abcd'})
return render_template('register.html',**self.context)
class LoginView(ADSView):
def dispatch_request(self):
return render_template('login.html',**self.context)
# class LoginView(views.View):
# def dispatch_request(self):
# return render_template('login.html',ads="今年过节不收礼,收礼只收脑白金")
# class RegistView(views.View):
# def dispatch_request(self):
# return render_template('register.html',ads="今年过节不收礼,收礼只收脑白金")
app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
app.add_url_rule('/regist/',view_func=RegistView.as_view('regist'))
@app.route('/')
def hello():
return "heello"
if __name__ == '__main__':
app.run()
基于调度方法的视图
- 根据请求方法来执行不同的方法的,如果用户发送的是get请求,就会执行这个类的get方法;如果用户发起的是post方法,就会执行这个类的post方法。其他的方法类似,这种方法使得代码更加简洁,使得执行get请求的代码放在get方法中,post请求的代码放在posy方法中。就不需要跟之前的
request.method == 'POST'
来搞了。 - 小例子
- py
from flask import Flask,views,render_template,request
app = Flask(__name__)
class LoginView(views.MethodView):
def __render(self,error=None):
return render_template('login.html',error=error)
def get(self,error=None):
# return render_template('login.html',error=error)
return self.__render()
def post(self):
username = request.form.get('username')
password = request.form.get('password')
if username == 'wanghui' and password == '111111':
return 'login success'
else:
# return render_template('login.html',error="username or password error,retry!")
# return self.get(error="username or password error,retry!")
return self.__render(error="username or password error,retry!")
app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True,port=9090)
- login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="" method="post">
<table>
<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>
</table>
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
</form>
</body>
</html>
类视图上面使用装饰器
两种类型的装饰器
- 如果使用的是函数视图, 那么定义的装饰器必须放在
app.route
下面,否则起不到任何作用
- 类视图的装饰器,需要重写类视图的
decorators
类属性,里面装的就是所有的装饰器
- 小例子:
from flask import Flask,request,views
from functools import wraps
app = Flask(__name__)
#定义装饰器
def login_required(func):
@wraps(func)
def wrapper(*args,**kwargs):
username = request.args.get('username')
if username and username == 'wanghui':
return func(*args,**kwargs)
else:
return "请先登录"
return wrapper
@app.route('/settings/')
@login_required
def settings():
return '这是设置页面'
#这样请求就行http://127.0.0.1:9091/settings/?username=wanghui
#类视图添加装饰器
class ProfileView(views.View):
decorators = [login_required]
def dispatch_request(self):
return "这是个人中心"
app.add_url_rule('/profile/',view_func=ProfileView.as_view('profile'))
蓝图
将大型项目分层解耦,实现模块化,结构更加清晰。可以将相同的模块放在同一个蓝图下,同一个文件夹中。方便管理。
- 基本语法:
- 在蓝图文件中导入Blueprint
from flask import Blueprint
user_bp = Blueprint('user',__name__) #相当于是定义`app = Flask(__name__)`
- 在主app文件中注册蓝图
from blueprints.user import user_bp
app.regist_blueprint(user_bp) #实现注册蓝图
- 如果想要某个蓝图下的所有
URL
的时候有个前缀,那么可以在定义蓝图的时候加上url_prefix
from flask import Blueprint
user_bp = Blueprint('user',__name__,url_prefix='/user')
# 特别注意斜杠
蓝图中的模板文件
蓝图模板文件查找:
- 如果项目中的
templates
文件夹中存在对应的模板文件,就可以直接使用 - 如果项目中的
templates
文件夹中存在相应的模板文件,那么就在定义蓝图的指定路径中查找,可以设置相对路径,就要在蓝图文件相同路径下的文件夹。
- 如果项目中的
from flask import Blueprint,render_template
news_bp = Blueprint('news',__name__,url_prefix='/news',template_folder='news')
@news_bp.route('/list/')
def news_list():
return render_template('news_list.html')
蓝图中的静态文件查找:
- 在模板文件中,加载静态文件,如果使用
url_for('static')
,那么只会在app指定的静态文件夹目录下查找静态文件 - 如果在加载静态文件的时候置顶了蓝图的名字,比如
url_for('news.static')
,那么会到蓝图指定的static_folder
下查找静态文件。
- 在模板文件中,加载静态文件,如果使用
url_for反转蓝图注意事项
- 注意
url_for
到蓝图中的视图函数的时候,要反转蓝图中的视图函数为url,那么就用该在使用url_for
的时候使用url_for('news.news_list')
不然就找不到这个endpoint。 - 即使在同一个蓝图中,反转视图函数,也要制定蓝图的名字
子域名实现
- 使用蓝图技术
- 在创建蓝图对象的时候要使用
subdomain
来指定这个子域名
from flask import Blueprint
cms_bp = Blueprint('cms',__name__,subdomain='cms')
- 需要在app文件中配置
app.config['SERVER_NAME']='baidu.com'
来指定跟域名
app.config['SERVER_NAME'] = 'crop.com:9099'
- 修改hosts文件配置解析
127.0.0.1 crop.com
127.0.0.1 cms.crop.com
5.访问
cms.crop.com:9099
综合实例代码
- 目录结构
blue_print_e
├── blue_print_e.py
├── blueprints
│ ├── bok.py
│ ├── cms.py
│ ├── movie.py
│ ├── news_css
│ │ └── news_list.css
│ ├── news.py
│ ├── news_tmp
│ │ └── news_list.html
│ └── user.py
├── static
│ └── news_list.css
└── templates
├── index.html
└── news_list.html
- 主app文件
blue_print_e.py
from flask import Flask,url_for,render_template
from blueprints.user import user_bp
from blueprints.news import news_bp
from blueprints.cms import cms_bp
app = Flask(__name__)
app.config['SERVER_NAME'] = 'crop.com:9099'
app.register_blueprint(user_bp)
app.register_blueprint(news_bp)
app.register_blueprint(cms_bp)
# ip地址不能有子域名
@app.route('/')
def hello_world():
print(url_for('news_tmp.news_list')) #使用蓝图名字.视图函数的名字
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True,port=9099)
blueprints/news.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint,render_template,url_for
news_bp = Blueprint('news_tmp',__name__,url_prefix='/news_tmp',template_folder='news_tmp',static_folder='news_css')
@news_bp.route('/list/')
def news_list():
print(url_for('news.news_detail'))
return render_template('news_list.html')
@news_bp.route('/detail')
def news_detail():
return "详情页面"
blueprints/user.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint
user_bp = Blueprint('user',__name__,url_prefix='/user')
@user_bp.route('/profile/')
def profile():
return "个人中心"
@user_bp.route('/settings/')
def settings():
return "设置页面"
blueprint/cms.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint
cms_bp = Blueprint('cms',__name__,subdomain='cms')
@cms_bp.route('/')
def index():
return 'cms index'
blueprints/news_css/
body {
color: fuchsia;
font-size: 90px;
background: red;
}
flask之三:视图高级的更多相关文章
- 【Flask】视图高级
# 视图高级笔记:### `add_url_rule(rule,endpoint=None,view_func=None)`这个方法用来添加url与视图函数的映射.如果没有填写`endpoint`,那 ...
- Flask之视图(一)
2.关于Flask 知识点 从Hello World开始 给路由传递参数 返回状态码 重定向 正则URL 设置cookie和获取cookie 扩展 上下文 请求钩子 Flask装饰器路由的实现 Fla ...
- 第五章 Flask视图高级
add_url_rule和app.route原理剖析 add_url_rule add_url_rule(rule,endpoint=None,view_func=None) 这个方法用来添加url与 ...
- Flask路由&视图
1 路由 1.1app.url_map 查看所有路由 from flask import Flask app = Flask(__name__) @app.route('/') def hello_ ...
- flask 在视图函数里操作数据库
在视图函数里操作数据库 在视图函数里操作数据的方式和在python shell中的联系基本相同,只不过需要一些额外的工作.比如把查询结果作为参数 传入模板渲染出来,或是获取表单的字段值作为提交到数据库 ...
- flask 在视图函数中验证表单
在视图函数中验证表单 因为现在的basic_form视图同时接受两种类型的请求:GET请求和POST请求.所以我们要根据请求方法的不同执行不同的代码.具体来说,首先是实例化表单,如果是GET请求,就渲 ...
- Flask之视图函数
视图示例 @app.route('/hello') def hello(): return 'Hello World' if __name__ == '__main__': app.run() 特殊的 ...
- Flask之视图(二)
2.2 扩展 上下文:相当于一个容器,保存了Flask程序运行过程中的一些信息. Flask中有两种上下文,请求上下文和应用上下文. 请求上下文(request context) request和se ...
- flask框架(四)——flask CBV视图类解析
CBV视图类的两种基本写法 #第一种写法class IndexView(views.View): methods = ['GET'] decorators = [auth, ] def dispatc ...
随机推荐
- Linux基础篇六:Linux文件属性和类型
-:代表文件 s: sorket文件 b:block块设备 (磁盘,光驱等) c:字符设备 l:连接文件 p:管道文件 d:代表目录文件 为了更加区分- (文件的具体类型),系统提供了file命令更加 ...
- 用windows下的Anaconda搭建Django虚拟环境
Django 是一个Python定制框架,可用于简便.快速的开发数据库驱动的web站点. 要使用Django,首先要建立一个虚拟工作环境. 那么,为什么要搭建虚拟环境呢?我们来看以下的开发场景: 假设 ...
- 浏览器加载、渲染html的顺序和页面优化
浏览器加载和渲染html的顺序 1. IE下载的顺序是从上到下,渲染(就是把请求的内容显示到浏览器屏幕上)的顺序也是从上到下,下载和渲染是同时进行的. 2. 在渲染到页面的某一部分时,其上面的所有部分 ...
- hdu5452
http://acm.hdu.edu.cn/showproblem.php?pid=5452 题意:给个图T(图G的最小生成树),然后再给定图G的剩余边,问你从图T中当且割一条边的情况再割图G中不属于 ...
- Qt platform plugin 'windows' 问题的解决方法
关于Qt 发布程序时遇到qt platform plugin ‘windows’问题的解决方法如下 遇到这个问题,一般应该已经把一部分dll拷贝到了发布的可执行文件同级目录, 我是直接添加C:\Qt ...
- vuex分模块管理
1.定义命名空间 dog.js export default { namespaced: true, // 局部状态 state: { name: "拉布拉多", age: 1 } ...
- reduced penetrance|COPE-PCG
生物医学大数据 Case study 由Human genome project提出之后,提出的精准医学.它的初衷是将数据standard后easy应用,我国重要重在疾病预警和疗效评价. 在疾病预警上 ...
- fiddler导出请求返回的响应数据
或者右键 选择response导出
- webgrind安装使用详细说明
webgrind是一个网页版的性能分析工具,它的主要作用就是分析xdebug生成的cachegrind文件,以一种界面友好详尽的方式来展示性能数据.试用了一下感觉还是很不错的,鉴于网上并没有一个系统介 ...
- JSP最终学习笔记
一.jsp基础1.JSP概念 Servlet是j2ee提供的动态资源开发技术,是以java的程序的形式进行开发,在java中书写HTML标签是一件十分头疼的事情,所以人们开发出了JSP,看起来像是HT ...