Flask视图高级

  1. add_url_rule和app.route原理剖析

    • add_url_rule(rule,endpoint=None,view_func = None):

      • 这个方法用来添加url与视图函数的映射。如果没有填写endpoint,那么默认会使用view_func的名字作为endpoint.以后再使用url_for的时候,就要看在映射的时候有没有传递‘endpoint’参数,如果传递了,那么就应该使用‘endpoint“指定的字符串,如果没有传递,那么就应该使用‘view_func‘的名字

    • app.route(rule,**options)装饰器:

      • 这个装饰器底层,其实也是使用‘add_url_rule‘来实现url与视图函数映射的

  2. 标准类视图及其用法

    • 类视图

      • 之前我们接触的视图都是函数,所以一般简称视图函数。其实视图也可以基于类来实现。类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图还需要通过app.add_url_rule(url_rule,view_func)来进行注册。以下将对两种视图进行详解

      • 有以下好处:

        • 可以继承,把一些共性的东西抽取出来放到视图中,子视图直接拿来用就可以了,但是也不是说所有的视图都要使用类视图,这个要根据情况而定。

    • 标准视图

      • 标准视图继承自flask.views.View,并且在子类中必须实现dispatch_request方法,这个方法类似于视图函数,也要返回一个基于Response或者其子类的对象。

      • dispatch_request方法,以后请求过来后,都会执行这个方法,这个方法的返回值就相当于之前的视图函数一样,也必须返回;Response或者子类的对象,或者是字符串,或者是元组

      • 必须通过app.add_url_rule(url_rule,endpoint,view_func)来做url与视图的映射.view_func这个参数,需要使用类视图下的as_view类方法类转换: 比如BaseView.as_view(‘list‘)

      • 如果指定了endpoint,那么在使用url_for反转的时候就必须使用‘endpoint‘指定的那个值,如果没有指定‘endpoint‘,那么就可以使用‘as_view‘(视图名字)中指定的视图名字来作为反转

        • + class BaseView(views.View):
            + #自定义方法,用来获取模板路径
            + def get_template_name(self):
              + raise NotImplementedError()
            + #必须实现的方法,用来处理请求的
            + def dispatch_request(self):
              + if request.method !=‘GET‘:
                + return ‘method error‘
              + #这里从self.get_data()中获取数据,子类应该实现这个方法
              + context = {‘data‘:self.get_data()}
              + return render_template(self.get_template_name(),**context)
          + class UserView(BaseView):
            + #实现从父类继承的获取模板路径的方法
            + def get_template_name(self):
              + return ‘user.html‘
            + #重写获取数据的方法
            + def get_data(self):
              + return [{‘username‘:‘fake‘,‘avatar‘:‘http://www.baidu.com‘}]
          + #类视图通过add_url_rule方法和url做映射
          + app.add_url_rule(‘/users/‘,view_func = ‘UserView.as_view(‘userview‘))
    • 基于调度方法的视图:

      • Flask还为我们提供了另外一种类视图flask.views.MethodView, 对每个HTTP方法执行不同的函数(映射到对应方法的小写的同名方法上),这对RESTful API 尤其有用,举例:

      • 基于调度方法的类视图,是根据请求的‘method‘来执行不同的方法的。如果用户是发送的‘get‘请求,那么将会执行这个类的‘get‘方法,如果用户发送的是‘post‘请求,那么将会执行这个类的‘post‘方法。其他的method类似,比如‘delete‘,‘put’

      • 这种方式,可以让代码更加简洁。所有和‘get‘请求相关的代码都放在‘get‘方法这种,所有和‘post‘请求相关的代码都放在‘post‘方法中.就不需要跟之前的函数一样。通过‘request.method‘==‘GET‘

        • + class UserAPI(views.MethodView):
            + #当客户段通过get方法进行访问的时候执行的函数
            + def get(self):
              + return jsonify({
              + ‘username‘:‘xiaotuo‘,
              + ‘avatar‘:‘http://www.baidu.com‘
              + })
            + #当客户端通过post方法进行访问的时候执行的函数
            + def post(self):
              + return ‘UNSUPPORTED‘
          + #通过add_url_rule添加类视图和url的映射,并且在as_view方法中指定url的名称,方便url_for函数调用
          + app.add_url_rule(‘/myuser/‘,view_func = UserAPI.as_view(‘userapiview‘))
      • 用类视图的一个缺陷就是比较难用装饰器来装饰,比如有时候需要做权限验证的时候,举例:

        • def user_required(f):
          ?
          + def decorator(*args,**kwargs):
            + if not g.user:
              + return ‘auth.failure‘
            + return f(*args,**kwargs)
          + return decorator
    • 类视图中使用装饰器

      • 如果使用的是函数视图,那么自己定义的装饰器必须放在app.route下面,否则这个装饰器就起不到任何作用

      • 类视图的装饰器,需要重写类视图的一个类属性decirators,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器

  3. 蓝图

    • 蓝图的基本使用

      • 蓝图的作用:就是让我们的Flask项目更加模块化,结构更加清晰,可以将相同模块的视图函数放在同一个蓝图下,同一个文件中,方便管理

      • 基本语法

        • 在蓝图文件中导入Blueprint: ‘

          • - from flask import Blueprint‘
            - user_bp = Blueprint(‘user‘,__ name __) #第一个参数是蓝图的名字
            - @user_bp.route(‘/index/‘)
            - def index():
              - return "这是用户界面"
            - @user_bp.route(‘/profile/‘)
            - def profile():
              - return "这是个人中心"
        • 在主app文件中注册蓝图

          • - from blueprints.user  import user_bp
            - app.regist_blueprint(user_bp)
      • 如果想要某个蓝图下的所有url都有一个url前缀,那么可以在定义蓝图的时候,指定url_prefix参数

        • user_bp = Blueprint(‘user‘,__ name__,url_prefix=‘/user‘)

        • 在定义url_prefix的时候,要注意后面的斜杠,如果给了,那么以后再定义url与视图函数的时候,就不要再在url前面加斜杠了

    • 蓝图模板文件的查找

      • 如果项目中的templates文件夹中有相应的模板文件,就直接使用了

      • 如果项目中的templates文件夹中没有相应的模板文件,那么就到定义蓝图的时候指定的路径中寻找,并且蓝图中指定的路径可以为相对路径。相对的是当前这个蓝图文件所在的目录。比如:

        • news_bp = Blueprint(‘news‘,__ name__,url_prefix=‘/news‘,template_folder=‘zhiliao‘)

        • 因为这个蓝图文件是在blueprints/news.py,那么就会到blueprints这个文件夹下的zhiliao文件夹中寻找模板文件

    • 蓝图中静态文件(img、CSS、jS)的查找规则:

      • 在模板文件中,加载静态文件,如果使用url_for(‘static‘),那么就只会在app指定的静态文件夹目录下查找静态文件。

      • 如果在加载静态文件的时候,指定的蓝图的名字,比如‘news.static‘,那么就会到这个蓝图指定的static_folder下查找静态文件

    • url_for反转蓝图中的视图函数为url:

      • 如果使用蓝图,那么以后想要反转蓝图中的视图函数为url,那么就应该在使用url_for的时候指定这个蓝图。比如news.news_list.否则就找不到这个endpoint。在模板中的url_for同样也是要满足这个条件。就是指定蓝图的名字

      • 即使在同一个蓝图中反转视图函数,也要指定蓝图的名字

    • 蓝图实现子域名:

      • 1.使用蓝图技术.

      • 2.在创建蓝图对象的时候,需要传递一个‘subdomain‘参数,来指定这个子域名 的前缀。列如: cms_bp = Blueprint(‘cms‘,__ name__,subdomain=‘cms‘)

      • 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.come

        • 域名和子域名都需要做映射

相关推荐