Flask视图高级
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与视图函数映射的
标准类视图及其用法
类视图
之前我们接触的视图都是函数,所以一般简称视图函数。其实视图也可以基于类来实现。类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图还需要通过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,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器
蓝图
蓝图的基本使用
蓝图的作用:就是让我们的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
域名和子域名都需要做映射