编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

3、Flask高级视图

wxchong 2024-06-27 01:38:33 开源技术 81 ℃ 0 评论

add_url_rule

类视图

标准视图

结合继承

基于调度方法的类视图

基于类视图使用装饰器

蓝图

蓝图的基本使用

蓝图下面的url_for

add_url_rule

add_url_rule方法,主要是手动像flask实例对象添加路径到处理函数的映射关系,它接收3个参数,第一个参数是访问的URI,第二个是这个URI的别名,主要是用户url_for,第三个的对应是处理函数;

from flask import Flask

app = Flask(__name__)

# 创建一个函数,返回一个字符串

def home():

return 'cce'

app.add_url_rule('/', endpoint='home',view_func=home) # 在这里将uri到处理函数的映射关系添加到flask对象

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

类视图

之前接触的都是函数视图,所以一般简称视图函数,其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图需要通过app.add_url_rule来注册类视图;

类视图的好处,可以继承把一些共性的东西抽取出来放到父级视图中;

标准视图

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

app = Flask(__name__)

class Home(View):

def dispatch_request(self): # 不论是GET还是POST方法都会都dispatch_request

return '1'

app.add_url_rule('/',view_func=Home.as_view('home')) # as_view将类视图转换为函数视图,他底层还是调用的dispatch_request函数,里面需要传入一个参数,也就是我们的endpoint;

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

结合继承

结合继承的好处案例一,当有类视图最终返回的都是一个json数据,那么我们就可以通过继承来简洁代码;

from flask import Flask, jsonify

from flask.views import View

app = Flask(__name__)

class JsonView(View):

def get_json_data(self):

raise NotImplementedError # 如果子类中没有定义get_json_data那么就抛出异常

def dispatch_request(self): # 因为类视图都需要调用dispatch_request所以直接在父级类里面加入dispatch_request,那么在继承该类的类视图就不需要定义dispatch_request

return jsonify(self.get_json_data()) # 此处的self.get_json_data调用的实际上是继承这个类的子类中的方法

class Home(JsonView):

def get_json_data(self): # 因为父类JsonView中有dispatch_request那么子类就不需要实现dispatch_request

return {'name': 'cce'}

app.add_url_rule('/', view_func=Home.as_view('home')) # as_view将类视图转换为函数视图,里面需要传入一个参数,也就是我们的endpoint;

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

基于调度方法的类视图

Flask还为我们提供了另一种类视图flask.views.MethodView,对每个http方法执行不同的类视图的方法,这对Restful API尤其有用;

from flask import Flask

from flask.views import MethodView

app = Flask(__name__)

class Home(MethodView):

def get(self):

return 'get'

def post(self):

return 'pos'

app.add_url_rule('/', view_func=Home.as_view('home')) # as_view将类视图转换为函数视图,里面需要传入一个参数,也就是我们的endpoint;

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

基于类视图使用装饰器

Flask已经考虑好了,我们只需要在自定义的类视图里面加入一个类属性decorators并且指明使用的装饰器即可;

对于methods和装饰器也是一样的,可以直接在类属性里面添加一个methods类属性指明支持的请求方法;

from flask import Flask, request, Response

from functools import wraps

from flask.views import View

app = Flask(__name__)

def login_required(func):

@wraps(func)

def wapper(*args, **kwargs):

if request.args.get('username', None):

return func(*args, **kwargs)

else:

return '你没有携带必要的参数'

return wapper

class Home(View):

decorators = [login_required] # 指明装饰器

methods = ['GET','POST'] # 指明允许请求的方法

def dispatch_request(self):

return 'cce'

app.add_url_rule('/', view_func=Home.as_view('home'))

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

蓝图

Blueprint,和Django中的app的概恋是差不多的,随着flask程序越来越复杂,我们需要对程序进行分层解耦,模块化的处理,比如只有一个run.py。有些功能需要多人分开来写,有些功能会有交错的可能,代码位置也不会在一起,这样可以用蓝图来开关一些模块(功能)和宏定义类似,但不是可插拔的应用而是一套可以注册在应用中的操作,并且可以注册多次。或者简单滴需要降低耦合,提高模块复用率。比如开发环境和应用环境的不同,可以用蓝图来切换环境。

url_prefix:定义蓝图的访问前缀,记住这里不要用/结尾;

其他的配置和创建flask实例的配置差不多;

蓝图的基本使用

# 目录层级结构

[root@Linux ~/edu]# tree

.

├── main.py

├── UserModel

│ ├── __init__.py

│ └── user.py

└── VideoModel

├── __init__.py

└── video.py

# main.py

from flask import Flask

from UserModel.user import User

from VideoModel.video import Video

app = Flask(__name__)

app.register_blueprint(User)

app.register_blueprint(Video)

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

# user.py

from flask import Blueprint

User=Blueprint('user',__name__, url_prefix='/user') # 第一个参数为蓝图的名字

@User.route('/')

def home():

return 'UserModel'

# video.py

from flask import Blueprint

Video = Blueprint('video', __name__, url_prefix='/video') # 第一个参数为蓝图的名字

@Video.route('/')

def home():

return 'VideoModel'

蓝图下面的url_for

当我们使用了蓝图之后,我们在主入口文件比如我们的main.py里面想要拿到蓝图里面的url_for,直接使用函数的名字那可能有点问题,那么我们需要找他,在取值的时候需要跟上Blueprnt的名字;

# 目录层级结构

[root@Linux ~/edu]# tree

.

├── main.py

├── UserModel

│ ├── __init__.py

│ └── user.py

└── VideoModel

├── __init__.py

└── video.py

# main.py

from flask import Flask,url_for

from UserModel.user import User

from VideoModel.video import Video

app = Flask(__name__)

app.register_blueprint(User)

app.register_blueprint(Video)

@app.route('/')

def home():

print(url_for('user.userhome')) # user是蓝图的名字,userhome是函数的名字

return '这是首页'

if __name__ == '__main__':

app.run("0.0.0.0", port=80, debug=True)

# user.py

from flask import Blueprint

User=Blueprint('user',__name__, url_prefix='/user')

@User.route('/')

def userhome():

return 'UserModel'

# video.py

from flask import Blueprint

Video = Blueprint('video', __name__, url_prefix='/video')

@Video.route('/')

def videohome():

return 'VideoModel'

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表