假设要定义两个路由:/v1/user/get
和/v1/book/get
,很容易想到的一种实现方法是:写3个python文件,app.py,book.py,user.py,代码分别如下:
- book.py
from flask import Blueprint
book = Blueprint("book", __name__)
@book.route("/get")
def get_book():
return "get book"
- user.py
from flask import Blueprint
user = Blueprint("user", __name__)
@user.route("/get")
def get_user():
return "get user"
- app.py
from flask import Flask
app = Flask(__name__)
app.register_blueprint(user, url_prefix='/v1/user')
app.register_blueprint(book, url_prefix='/v1/book')
这种写法没问题,但最近在看https://coding.imooc.com/class/220.html的课程中学到了一种更pythonic的写法,设计思路如下:
需要模仿Blueprint
自定义一个类Redprint
,在类中实现两个必要的方法:route()
实现一个注册路由的装饰器,register()
用来将Redprint对象注册到Blueprint上,代码如下:
- redprint.py
class Redprint:
def __init__(self, name):
self.name = name
self.mound = []
def route(self, rule, **options):
def decorator(f):
self.mound.append((f, rule, options))
return f
return decorator
def register(self, bp, url_prefix=None):
if url_prefix is None:
url_prefix = '/' + self.name
for f, rule, options in self.mound:
# 仿照 Blueprint 中 route 方法的写法
endpoint = self.name + '+' + options.pop('endpoint', f.__name__)
bp.add_url_rule(url_prefix + rule, endpoint, f, **options)
- book.py
from redprint import Redprint
api = Redprint("book")
@api.route("/get")
def get_book():
return "get book"
- user.py
from redprint import Redprint
api = Redprint("user")
@api.route("/get")
def get_user():
return "hello"
@api.route("/create")
def create_user():
return "create user"
- app.py
from flask import Flask
def register_blueprints(app):
from flask import Blueprint
from test import book, user
bp_v1 = Blueprint('v1', __name__)
# 将Redprint注册到Blueprint中
book.api.register(bp_v1)
user.api.register(bp_v1)
# 将Blueprint注册到APP中
app.register_blueprint(bp_v1, url_prefix='/v1')
app = Flask(__name__)
register_blueprints(app)