我正在尝试使用蓝图在 Flask 中创建一个“模块化应用程序”。
但是,在创建模型时,我遇到了必须引用应用程序才能获得db
Flask-SQLAlchemy 提供的 -object 的问题。我希望能够将一些蓝图与多个应用程序一起使用(类似于 Django 应用程序的使用方式),所以这不是一个好的解决方案。*
- 可以进行切换,让蓝图创建
db
实例,然后应用程序将其与蓝图的其余部分一起导入。但是,任何其他希望创建模型的蓝图都需要从该蓝图而不是应用程序导入。
我的问题是:
- 有没有一种方法可以让蓝图定义模型,而无需了解它们以后使用的应用程序——并且将多个蓝图组合在一起?我的意思是必须从您的蓝图中导入应用程序模块/包。
- 我一开始就错了吗?蓝图不是独立于应用程序并且是可再分发的(à la Django 应用程序)吗?
- 如果不是,那么您应该使用什么模式来创建类似的东西?烧瓶扩展?您是否应该干脆不这样做 - 并且可能集中所有模型/模式 à la Ruby on Rails?
编辑:我自己现在一直在考虑这个问题,这可能与 SQLAlchemy 比 Flask 更相关,因为你必须
declarative_base()
在声明模型时。无论如何,这一定来自某个地方!也许最好的解决方案是将项目的模式定义在一个地方并将其分散开,就像 Ruby on Rails 那样。声明式 SQLAlchemy 类定义实际上更像 schema.rb,而不是 Django 的 models.py。我想这也会使迁移(来自alembic或sqlalchemy-migrate )更容易使用。
我被要求提供一个示例,所以让我们做一些简单的事情:假设我有一个描述“平面页面”的蓝图——存储在数据库中的简单、“静态”内容。它使用一个只有短名称(用于 URL)、标题和正文的表格。这是simple_pages/__init__.py
:
from flask import Blueprint, render_template
from .models import Page
flat_pages = Blueprint('flat_pages', __name__, template_folder='templates')
@flat_pages.route('/<page>')
def show(page):
page_object = Page.query.filter_by(name=page).first()
return render_template('pages/{}.html'.format(page), page=page_object)
然后,最好让这个蓝图定义它自己的模型(this in simple_page/models.py
):
# TODO Somehow get ahold of a `db` instance without referencing the app
# I might get used in!
class Page(db.Model):
name = db.Column(db.String(255), primary_key=True)
title = db.Column(db.String(255))
content = db.Column(db.String(255))
def __init__(self, name, title, content):
self.name = name
self.title = title
self.content = content
这个问题与:
和其他各种,但所有回复似乎都依赖于导入应用程序的db
实例,或者做相反的事情。“ Large app how to” wiki 页面也使用了“import your app in your blueprint”模式。
* 由于官方文档显示了如何在蓝图中创建路线、视图、模板和资产,而不关心它“在”什么应用程序,我假设蓝图通常应该可以跨应用程序重用。然而,如果没有独立的模型,这种模块化似乎并没有那么有用。
既然蓝图可以多次挂接到应用程序中,那么在蓝图中拥有模型可能只是错误的方法?