gpt4 book ai didi

python - Flask 中的嵌套蓝图?

转载 作者:太空狗 更新时间:2023-10-29 18:03:44 31 4
gpt4 key购买 nike

我对 Flask 还是个新手,所以可能有一个明显的方法可以实现这一点,但到目前为止我还无法从文档中弄清楚。我的应用程序分为几个几乎完全不同的部分,它们共享诸如用户/ session /安全和基本模板之类的东西,但大部分都没有太多交互,并且应该在不同的路径下路由,例如 /part1/...。我认为这几乎正是蓝图的用途。但是,如果我需要在蓝图下进一步分组路由和逻辑怎么办?

例如,我有 blueprint1url_prefix='/blueprint1' 并且可能在其下我想要围绕用户共享照片和其他内容的 View 集合用户评论他们。我想不出比以下更好的方法了:

# app/blueprints/blueprint1/__init__.py

blueprint1 = Blueprint('blueprint1', __name__, template_folder='blueprint1')

@blueprint1.route('/photos')
def photos_index():
return render_template('photos/index.html')

@blueprint.route('/photos/<int:photo_id>')
def photos_show(photo_id):
photo = get_a_photo_object(photo_id)
return render_template('photos/show.html', photo=photo)

@blueprint.route('/photos', methods=['POST'])
def photos_post():
...

这里的问题是,所有与 blueprint1 的照片部分相关的 View 都位于“顶层”,可能还有视频或音频或其他内容的蓝图(名为 videos_index ()...)。有没有什么方法可以以更分层的方式对它们进行分组,例如模板如何位于 'blueprint1/photos' 子目录下?当然,我可以将所有照片 View 放在它们自己的模块中,以便将它们分开组织,但是如果我想将父 'blueprint1/photos' 路径更改为其他路径怎么办?我确定我可以发明一个函数或装饰器,将相关路由分组在同一根路径下,但我仍然必须使用 photos_ 前缀命名所有函数并像 url_for 一样引用它们('blueprint1.photos_show') 当 Flask 应用变大并且您需要将相似的部分分组和划分在一起时,蓝图似乎是答案,但是当蓝图本身变大时您不能做同样的事情。

作为引用,在 Laravel 中,您可以将相关的“ View ”分组到 Controller 类中,其中 View 是方法。 Controller 可以驻留在分层命名空间中,例如 app\Http\Controllers\Blueprint1\Photocontroller,路由可以像这样分组在一起

Route::group(['prefix' => 'blueprint1'], function() {

Route::group(['prefix' => 'photos'], function() {

Route::get('/', ['as' => 'blueprint.photos.index', 'uses' => 'ModelApiController@index']);
Route::post('/', ['as' => 'blueprint.photos.store', 'uses' => 'ModelApiController@store']);
Route::get('/{id}', ['as' => 'blueprint.photos.get', 'uses' => 'ModelApiController@get'])
->where('id', '[0-9]+');

});

});

路由可以像 action('Blueprint1\PhotoController@index') 一样获取。

如果我能制作照片蓝图,那么只需执行 blueprint1.register_blueprint(photos_blueprint, url_prefix='/photos') 之类的操作,这些问题就迎刃而解了。不幸的是,Flask 似乎不支持这样的嵌套蓝图。有没有其他方法可以解决这个问题?

最佳答案

更新

Flask 2 发布时支持嵌套蓝图。

[开始:来自文档的部分]

嵌套蓝图

可以在另一个蓝图上注册一个蓝图。

parent = Blueprint('parent', __name__, url_prefix='/parent')
child = Blueprint('child', __name__, url_prefix='/child')
parent.register_blueprint(child)
app.register_blueprint(parent)

子蓝图将获得父名称作为其名称的前缀,子 URL 将以父 URL 前缀为前缀。

url_for('parent.child.create')
/parent/child/create

特定于蓝图的请求函数等在父项中注册后会为子项触发。如果子级没有可以处理给定异常的错误处理程序,则将尝试父级的。

[ END:来自文档的部分 ]

来源:https://flask.palletsprojects.com/en/2.0.x/blueprints/#nesting-blueprints


旧答案

我的 hacky work around 是我创建了一个名为 ParentBP 的类,它具有以下代码

from typing import List
from flask import Blueprint

class ParentBP(object):
name: str
url_prefix: str
subdomain: str
blueprints: List[Blueprint]

def __init__(self, name="", url_prefix="", subdomain="") -> None:
self.name = name
self.url_prefix = url_prefix
self.subdomain = subdomain
self.blueprints = []

def register_blueprint(self, bp: Blueprint) -> None:
bp.name = self.name + "-" + bp.name
bp.url_prefix = self.url_prefix + (bp.url_prefix or "")
if self.subdomain:
bp.subdomain = self.subdomain
self.blueprints.append(bp)

所以你可以像下面的蓝图那样调用它

blueprint1 = Blueprint("blueprint1", __name__)
blueprint2 = Blueprint("blueprint2", __name__, url_prefix="/bp2")

api_v1 = ParentBP("api-v1", url_prefix="/api/v1")
api_v1.register_blueprint(blueprint1)
api_v1.register_blueprint(blueprint)

为了使界面类似于将蓝图正常注册到 Flask 应用程序,我扩展了 Flask 类,如下所示

class ExtendedFlask(Flask):

def register_blueprint(self, blueprint: Union[Blueprint, ParentBP], **options: Any) -> None:
if isinstance(blueprint, ParentBP):
for bp in blueprint.blueprints:
super().register_blueprint(bp, **options)
else:
return super().register_blueprint(blueprint, **options)

现在您可以正常进行以下操作了

app = ExtendedFlask(__name__)
app.register_blueprint(api_v1)

关于python - Flask 中的嵌套蓝图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33003178/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com