Flask系列教程(5)——视图高级

来源:互联网 发布:latex for mac 编辑:程序博客网 时间:2024/06/06 05:29

flask入门(视图高级)

类视图:

之前我们接触的视图都是函数,所以一般简称视图函数。其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图还需要通过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]...

蓝图(blueprint):

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

from flask import Blueprintbp = 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 Flaskimport userapp = 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 Blueprintbp = Blueprint('admin',__name__,subdomain='admin')@bp.route('/')def admin():    return 'Admin Page'

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

from flask import Flaskimport admin# 配置`SERVER_NAME`app.config['SERVER_NAME'] = 'example.com:8000'# 注册蓝图,指定了subdomainapp.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上出现。

对Python和Flask感兴趣,可以加群:526929231一起讨论和学习哦。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小鸡脚扭伤了该怎么办 跳高比赛最终成绩相等怎么办 热车1200怠速降不下来怎么办 大腿根骨髓水肿越来越疼怎么办 倒库方向打晚了怎么办 签吻芳颜祛斑液脸脱皮怎么办 3d右边工具栏消失了怎么办 3d菜单栏消失了怎么办 觉得自己性无能不敢谈对象怎么办 护士面试时被问到病人坠床怎么办 三次元仪器坏了怎么办 运动同手同脚怎么办 狗狗突然害怕不敢走路怎么办 一岁半宝宝因为害怕不敢走路怎么办 猫把背拱起来怎么办 穿猫跟鞋走路不稳怎么办 狗狗后腿内八字怎么办 快走后小腿粗了怎么办? 猫的嘴巴烂了怎么办 苹果8丢了已关机怎么办 肚子吃多了难受怎么办 喝水喝的肚子胀怎么办 肚子吃撑了难受怎么办 肚子撑得想吐怎么办 吃饭吃的太饱怎么办 吃饭吃的太撑怎么办 跑步迈不开步子怎么办 踏步走步子反了怎么办 微信不支持计步怎么办 肝癌二次介入后头晕心慌怎么办 跑步跑得胃疼怎么办 如果世界上的猪都死了怎么办 我和我老婆吵架怎么办 我和我老婆吵架了怎么办 智障人士父母死后怎么办 依赖性太强的人怎么办 高考只有一门写准考证号怎么办 ps做动画不流畅怎么办 ff15引擎剑卖了怎么办 fgo从者满了怎么办 游泳池的水喝了怎么办