之前我们已经了解过了视图函数的大概用法,本节深入了解一下视图函数
endpint
参数是写在注册路由的装饰器中的一个参数,学名叫端点,我们可以理解为函数的别名。原来我们翻转视图函数的url
的时候是直接通过是如函数的名字,如url_for('函数名')
,现在我们可以指定一个endpoint='fbv'
参数来进行翻转url
。如果不指定endpoint,默认就以函数名作为端点名。
实例:
| @app.route('/fbvtest/',methods=['GET','POST'],endpoint='fbv') |
| def fbvtest(): |
| url_demo = url_for('fbv') |
| return '利用视图函数别名翻转的url为:{}'.format(url_demo) |
关键词:
- 利用
@app.route()
的endpoint='fbv'
参数可以自由指定端点名,url_for可以根据指定的端点名进行翻转。
(1) 首先写一个小视图函数
| |
| |
| |
| @app.route('/source_code_demo/',endpoint='source_code') |
| def source_code_demo(): |
| |
| return 'source_code_demo' |
(2) 查看app.route()
源码
| ... |
| def route(self, rule, **options): |
| ... |
| def decorator(f): |
| endpoint = options.pop('endpoint', None) |
| self.add_url_rule(rule, endpoint, f, **options) |
| return f |
| return decorator |
解析:
-
,发现route()
返回的是decorator
函数地址,然后基于语法糖和装饰器的原理,decorator会加括号运行,像这样decorator(source_code_demo)
-
decorator
函数中首先取出endpoint
,然后运行self.add_url_rule(rule, endpoint, f, **options)
-
所以 self.add_url_rule(rule, endpoint, f, **options)
就是注册路由的核心
(3) 点进self.add_url_rule(rule, endpoint, f, **options)
查看源码,
再点进_endpoint_from_view_func(view_func)
查看源码
| |
| ... |
| |
| @setupmethod |
| def add_url_rule(self, rule, endpoint=None, view_func=None, |
| provide_automatic_options=None, **options): |
| |
| ... |
| |
| if endpoint is None: |
| endpoint = _endpoint_from_view_func(view_func) |
| options['endpoint'] = endpoint |
| methods = options.pop('methods', None) |
| |
| |
| |
| |
| if methods is None: |
| methods = getattr(view_func, 'methods', None) or ('GET',) |
| |
| ... |
| def _endpoint_from_view_func(view_func): |
| """Internal helper that returns the default endpoint for a given |
| function. This always is the function name. |
| """ |
| assert view_func is not None, 'expected view func if endpoint ' \ |
| 'is not provided.' |
| return view_func.__name__ |
解析:
-
由上述代码我们可以直到如果没有指定endpoint
,我们调用了 _endpoint_from_view_func()
-
观察_endpoint_from_view_func
函数我们可以知道,返回了视图函数的名字给了endpoint
赋值
-
methos
没有指定会给methos赋默认值('GET',)
小结:
self.add_url_rule(rule, endpoint, f, options)
就是注册路由的核心
- 观察
_endpoint_from_view_func
函数我们可以知道,返回了视图函数的名字给了endpoint
赋值
methos
没有指定会给methods
赋默认值('GET',)
通过看上一个小节写的源码,现在我们知道了app.route() 的核心就是self.add_url_rule(rule, endpoint, f, options)
就是注册路由的核心。所以我们可以直接使用app.add_url_rule()
的方式来注册路由。
实例:
| def add_url_test(): |
| |
| return '实现了add_url方式注册路由' |
| |
| app.add_url_rule('/add_url_test/',endpoint='add_demo',view_func=add_url_test) |
我们在平时的开发的过程中,很多需要权限验证的功能需要用到装饰器,下面的代码是如何在flask中实现一个装饰器。
| from flask import Flask, request |
| from functools import wraps |
| |
| app = Flask(__name__) |
| |
| def login_verify(func): |
| @wraps(func) |
| def wrapper(*args, **kwargs): |
| user_name = request.args.get('user') |
| password = request.args.get('password') |
| if user_name == 'mark' and password == '123': |
| return func(*args,**kwargs) |
| else: |
| return '请登录' |
| return wrapper |
| |
| @app.route('/') |
| def hello_world(): |
| return 'Hello World!' |
| |
| @app.route('/my_info/') |
| @login_verify |
| def my_info(): |
| return '个人信息页面' |
关键词:
- 装饰器一定要写在注册路由的下面,写在视图函数的上面。
- 装饰器内部一定要使用
@wraps(func)
方法,用于保护被装饰函数的属性。
| from flask import Flask, views, request, url_for |
| from functools import wraps |
| |
| def login_verify(func): |
| @wraps(func) |
| def wrapper(*args, **kwargs): |
| user_name = request.args.get('user') |
| password = request.args.get('password') |
| if user_name == 'mark' and password == '123': |
| return func(*args,**kwargs) |
| else: |
| return '请登录' |
| return wrapper |
| |
| class CBVTest(views.MethodView): |
| |
| methods = ['GET','POST'] |
| decorators = [login_verify,] |
| |
| def get(self): |
| print(url_for('cbvtest')) |
| return 'cbv_get' |
| def post(self): |
| return 'cbv_post' |
| app.add_url_rule('/cbvtest',view_func=CBVTest.as_view(name='cbvtest'),endpoint='end_demo') |
讲解:
-
首先从flask中导入 views
-
写一个类一定要继承 views.MethodView
-
在类中写methods = ['GET','POST']
可以指定可接受的请求类型
-
在类中写decorators = [login_verify,]
可以指定装饰器,第一个装饰器是最里层函数依次往后包裹
-
在类中写def get(self):
用于获取get请求
-
在类中写 def post(self):
用于获取post请求
-
添加路由的方法使用
| app.add_url_rule( |
| '路由',view_func=CBVTest.as_view(name='自定义一个端点名字')) |
其原理是CBVTest.as_view(name='自定义一个端点名字')
会返回一个函数,name是为这个函数命的名字,可以通过这个函数进行分发请求等操作。
| @app.route和app.add_url_rule参数: |
| rule, URL规则 |
| view_func, 视图函数名称 |
| endpoint = None, 名称,用于反向生成URL,即: url_for('名称') |
| methods = None, 允许的请求方式,如:["GET", "POST"] |
(1) 对URL最后的 / 符号是否严格要求 strict_slashes = False
| strict_slashes = False |
| ''' |
| @app.route('/index', strict_slashes=False) |
| #访问http://www.xx.com/index/ 或http://www.xx.com/index均可 |
| @app.route('/index', strict_slashes=True) |
| #仅访问http://www.xx.com/index |
| ''' |
(2) 重定向到指定地址redirect_to=“ ”
| @app.route("/",redirect_to='/home/') |
| def index(): |
| |
| return '根路径' |
| |
| @app.route("/home/") |
| def admin_demo(): |
| |
| return 'home路径' |
(3) 为函数提供默认参数值
| defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'} |
(4)子域名设置subdomain=“ ”
| from flask import Flask,url_for |
| |
| app = Flask(__name__) |
| app.debug = True |
| ''' |
| 先在hosts设置域名解析(就是在本机的hosts文件上编辑上域名对应ip的关系) |
| 域名解析会先解析本地如果没有再解析dns服务器 |
| C:\Windows\System32\drivers\etc\hosts |
| |
| 127.0.0.1 mark.com |
| 127.0.0.1 admin.mark.com |
| |
| ''' |
| app.config['SERVER_NAME'] = 'mark.com:5000' |
| |
| @app.route("/") |
| def index(): |
| |
| return '设置域名成功' |
| |
| @app.route("/admin_demo/",subdomain='admin') |
| def admin_demo(): |
| |
| return '设置子域名成功' |
| |
| ''' |
| 在浏览器中访问主域名 |
| mark.com:5000/ |
| |
| 在浏览器中访问子域名 |
| admin.mark.com:5000/admin_demo/ |
| |
| 注意:后面跟的path路径部分正常写 |
| ''' |
| |
| if __name__ == '__main__': |
| app.run(host='127.0.0.1',port=5000) |