04_视图函数和视图类_自定义装饰器_注册路由

1 视图函数

之前我们已经了解过了视图函数的大概用法,本节深入了解一下视图函数

1.1 endpoint简介

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)

image-20210417221048808

关键词:

  • 利用@app.route()endpoint='fbv'参数可以自由指定端点名,url_for可以根据指定的端点名进行翻转。

1.2 装饰器注册路由源码浅析

(1) 首先写一个小视图函数

# 注册装饰器的原理
# 1 v = app.route('/source_code_demo/',endpoint='source_code')
# 2 v(source_code_demo)
@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 the methods are not given and the view_func object knows its
        # methods we can use that instead.  If neither exists, we go with
        # a tuple of only ``GET`` as default.
        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赋值
  • methods没有指定会给methos赋默认值('GET',)

小结:

  1. self.add_url_rule(rule, endpoint, f, options)就是注册路由的核心
  2. 观察_endpoint_from_view_func函数我们可以知道,返回了视图函数的名字给了endpoint赋值
  3. methods没有指定会给methods赋默认值('GET',)

1.3 另一种注册路由的方式——app.add_url_rule()

通过看上一个小节写的源码,现在我们知道了app.route() 的核心就是self.add_url_rule(rule, endpoint, f, options)就是注册路由的核心。所以我们可以直接使用app.add_url_rule()的方式来注册路由。

实例:

def add_url_test():

    return '实现了add_url方式注册路由'
                 # url                       端点                 函数地址
app.add_url_rule('/add_url_test/',endpoint='add_demo',view_func=add_url_test)

1.4 视图函数中添加自定义装饰器

我们在平时的开发的过程中,很多需要权限验证的功能需要用到装饰器,下面的代码是如何在flask中实现一个装饰器。

server.py

from flask import Flask, request, render_template
from functools import wraps

app = Flask(__name__)


def login_verify(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        user_name = request.args.get('username')
        password = request.args.get('password')
        if user_name == 'mark' and password == '123':
            return func(*args, **kwargs)
        else:
            return '请登录'

    return wrapper


@app.route('/login/')
def hello_world():
    return render_template('login.html')


@app.route('/my_info/')
@login_verify
def my_info():
    return '个人信息页面'


if __name__ == '__main__':
    app.run(debug=True)

templates/login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>登录界面</title>
</head>
<body>
<form action="/my_info/" method="GET">
    用户:<input type="text" name="username">
    密码:<input type="text" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>

image-20210417222332564

image-20210417222324101

关键词

  1. 装饰器一定要写在注册路由的下面,写在视图函数的上面。
  2. 装饰器内部一定要使用@wraps(func)方法,用于保护被装饰函数的属性。

2 视图类

2.1 视图类的基本写法

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')

讲解:

  1. 首先从flask中导入 views

  2. 写一个类一定要继承 views.MethodView

  3. 在类中写methods = ['GET','POST'] 可以指定可接受的请求类型

  4. 在类中写decorators = [login_verify,]可以指定装饰器,第一个装饰器是最里层函数依次往后包裹

  5. 在类中写def get(self):用于获取get请求

  6. 在类中写def post(self):用于获取post请求

  7. 添加路由的方法使用

    app.add_url_rule(
        '路由',view_func=CBVTest.as_view(name='自定义一个端点名字'))
    

    其原理是CBVTest.as_view(name='自定义一个端点名字')会返回一个函数,name是为这个函数的名字,可以通过这个函数进行分发请求等操作。

3 详细讲解注册路由的参数:

3.1 常用的参数

@app.route和app.add_url_rule参数:
rule, URL规则
view_func, 视图函数名称
endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]

3.2 不常用的参数(了解)

(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' # 这个代表访问这个域名的时候要访问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) # 测试服务器不稳定,尽量手动制定ip和端口
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值