zoukankan      html  css  js  c++  java
  • flask全栈开发4 高级视图

    第五章 高级视图

    5.1 第一节 类视图

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

    标准视图:

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

    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尤其有用,以下将用一个例子来进行讲解:

        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
    

    如果要在类视图上进行装饰,只能在as_view函数上进行装饰了,使用方式如下:

    view = user_required(UserAPI.as_view('users'))
    app.add_url_rule('/users/',view_func=view)
    

    但是一个好消息是,从Flask 0.8开始,还可以通过在类中添加decorators属性来实现对视图的装饰:

    class UserAPI(views.MethodView):
        decorators = [user_required]
        ...
    

    5.2 第二节 蓝图和子域名

    蓝图:

    之前我们写的url和视图函数都是处在同一个文件,如果项目比较大的话,这显然不是一个合理的结构,而蓝图可以优雅的帮我们实现这种需求。使用蓝图一般是将相同的URL前缀,比如/user/:id/user/profile/这样的地址,他们的特点都是以user开头的,那么可以将这一类的url放在一个模块中,达到项目的模块化,以下看一个使用蓝图的文件的例子(user.py):

    from flask import Blueprint
    bp = Blueprint('user',__name__,url_prefix='/user/')
    
    @bp.route('/')
    def index():
        return "User's Index Page"
    
    @bp.route('/profile/')
    def profile():
        return "User's profile Page"
    

    然后我们在主程序中,通过app.register_blueprint()方法将这个蓝图注册进url映射中,看下主app的实现:

    from flask import Flask
    import user
    
    app = Flask(__name__)
    app.register_blueprint(user.bp)
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0',port=9000)
    

    以后访问/user//user/profile/,都是执行的user.py文件中的视图函数,这样就实现了项目的模块化。

    以上是对蓝图的一个简单介绍,但是使用蓝图还有几个需要注意的地方,就是在蓝图如何寻找静态文件、模板文件,url_for函数如何反转url,以下分别进行解释:

    寻找静态文件:

    默认不设置任何静态文件路径,Jinja2会在项目的static文件夹中寻找静态文件。也可以设置其他的路径,在初始化蓝图的时候,Blueprint这个构造函数,有一个参数static_folder可以指定静态文件的路径,如:

      bp = Blueprint('admin',__name__,url_prefix='/admin',static_folder='static')
    

    static_folder可以是相对路径(相对蓝图文件所在的目录),也可以是绝对路径。在配置完蓝图后,还有一个需要注意的地方是如何在模板中引用静态文件。在模板中引用蓝图,应该要使用蓝图名+.+static来引用,如下所示:

      <link href="{{ url_for('admin.static',filename='about.css') }}">
    
    寻找模板文件:

    跟静态文件一样,默认不设置任何模板文件的路径,将会在项目的templates中寻找模板文件。也可以设置其他的路径,在构造函数Blueprint中有一个template_folder参数可以设置模板的路径,如下所示:

      bp = Blueprint('admin',__name__,url_prefix='/admin',template_folder='templates')
    

    模板文件和静态文件有点区别,以上代码写完以后,如果你渲染一个模板return render_template('admin.html')Flask默认会去项目根目录下的templates文件夹中查找admin.html文件,如果找到了就直接返回,如果没有找到,才会去蓝图文件所在的目录下的templates文件夹中寻找。

    url_for生成url

    url_for生成蓝图的url,使用的格式是:蓝图名称+.+视图函数名称。比如要获取admin这个蓝图下的index视图函数的url,应该采用以下方式:

      url_for('admin.index')
    

    其中这个蓝图名称是在创建蓝图的时候,传入的第一个参数。bp = Blueprint('admin',__name__,url_prefix='/admin',template_folder='templates')

    子域名:

    子域名在许多网站中都用到了,比如一个网站叫做xxx.com,那么我们可以定义一个子域名cms.xxx.com来作为cms管理系统的网址,子域名的实现一般也是通过蓝图来实现,在之前章节中,我们创建蓝图的时候添加了一个url_prefix=/user作为url前缀,那样我们就可以通过/user/来访问user下的url。但使用子域名则不需要。另外,还需要配置SERVER_NAME,比如app.config[SERVER_NAME]='example.com:9000'。并且在注册蓝图的时候,还需要添加一个subdomain的参数,这个参数就是子域名的名称,先来看一下蓝图的实现(admin.py):

    from flask import Blueprint
    bp = Blueprint('admin',__name__,subdomain='admin')
    
    @bp.route('/')
    def admin():
        return 'Admin Page'
    

    这个没有多大区别,接下来看主app的实现:

    from flask import Flask
    import admin
    
    # 配置`SERVER_NAME`
    app.config['SERVER_NAME'] = 'example.com:8000'
    # 注册蓝图,指定了subdomain
    app.register_blueprint(admin.bp)
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0',port=8000,debug=True)
    

    写完以上两个文件后,还是不能正常的访问admin.example.com:8000这个子域名,因为我们没有在host文件中添加域名解析,你可以在最后添加一行127.0.0.1 admin.example.com,就可以访问到了。另外,子域名不能在127.0.0.1上出现,也不能在localhost上出现。

  • 相关阅读:
    java图书管理系统界面版本+mysql数据库
    java数组实现的超市管理系统(控制台)
    Action<T>和Func<T>委托事例
    简单的委托示例
    使用静态方法CreateInstance()创建数组
    Span复习
    与预定义类型的用户类型强制转换
    实现自定义的索引运算符
    比较运算符的重载
    算术运算符的重载
  • 原文地址:https://www.cnblogs.com/sky-ai/p/12826955.html
Copyright © 2011-2022 走看看