zoukankan      html  css  js  c++  java
  • 【6】Flask 视图函数和视图类

    视图函数和视图类

    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)
    

    关键词:

    • 利用@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赋值
    • methos没有指定会给methos赋默认值('GET',)

    小结:

    1. self.add_url_rule(rule, endpoint, f, options)就是注册路由的核心
    2. 观察_endpoint_from_view_func函数我们可以知道,返回了视图函数的名字给了endpoint赋值
    3. methos没有指定会给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中实现一个装饰器。

    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 '个人信息页面'
    

    关键词

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

    2 视图类

    2.1 视图类的基本写法

    from flask import Flask, views, request, url_for
    from functools import wraps
    app = Flask(__name__)
    def login_verify(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            user = request.args.get('user')
            pwd = request.args.get('pwd')
            if user == 'mark' and pwd == '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('end_demo'))
            return 'cbv_get'
        def post(self):
            return 'cbv_post'
    app.add_url_rule('/cbvtest/',view_func=CBVTest.as_view(name='cbvtest'),endpoint='end_demo')
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    如图:

    控制台输出:

    浏览器输出

    讲解:

    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 详细讲解注册路由的参数:

    常用的参数

    @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:WindowsSystem32driversetchosts
    
    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和端口
    

  • 相关阅读:
    《Docker技术入门与实践》Docker入门4-使用Dockerfile创建镜像
    《Docker技术入门与实践》Docker入门3-网络基础配置
    《Docker技术入门与实践》Docker入门2-数据管理
    Git管理多个SSH密钥,Git多帐号配置
    《Docker技术入门与实践》Docker入门
    java获取汉字笔画数
    NSBundle、UIImageView、uibutton
    动画帧的使用
    结构体的转换
    IOS字符串的处理例子
  • 原文地址:https://www.cnblogs.com/remixnameless/p/13286164.html
Copyright © 2011-2022 走看看