【发布时间】:2012-10-15 01:24:48
【问题描述】:
我正在尝试使用蓝图在 Flask 中创建一个“模块化应用程序”。
但是,在创建模型时,我遇到了必须引用应用程序才能获得 Flask-SQLAlchemy 提供的 db-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)
那么,最好让这个蓝图定义它自己的模型(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 页面也使用“在您的蓝图中导入您的应用程序”模式。
* 由于官方文档展示了如何在蓝图中创建路由、视图、模板和资产,而不关心它“在”什么应用程序,我假设蓝图通常应该可以跨应用程序重用.但是,如果没有独立的模型,这种模块化似乎没有用。
既然蓝图可以多次挂接到应用程序中,那么在蓝图中添加模型可能就是错误的方法?
【问题讨论】:
-
您作为可插入应用程序创建的蓝图是否需要定义它们使用的模型?或者它们可以简单地从应用程序中给定模型吗?如果是前者,您能否举例说明您正在尝试创建的一种需要定义自己的模型的可重用蓝图?
-
我提供了一个简单的例子,就像你问的那样。在这种情况下很难谈论“需要”:如果这是从根本上错误的方法,它不需要定义自己的模型,但我的印象是你“应该”这样做。但是,我可以理解 Flask 是否更适合像 RoR 那样在您的应用程序中定义架构并“提供”给各种插件。我想在那种情况下,您会使用配置来提供它吗?
-
为什么this solution 在您的情况下不起作用?它不引用模型或蓝图模块中的应用程序。
-
它仍然依赖于共享命名空间
shared.apps,这使得跨应用程序使用相同的蓝图变得很困难(在这样的命名空间上可能没有任何协议)
标签: python flask flask-sqlalchemy