Closed. This question is opinion-based。它当前不接受答案。












想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。

2年前关闭。



Improve this question




我正在尝试使用蓝图在Flask中创建一个“模块化应用程序”。
但是,在创建模型时,我遇到了必须引用该应用程序才能获取Flask-SQLAlchemy提供的db -object的问题。我希望能够在多个应用程序中使用一些蓝图(类似于Django应用程序的使用方式),所以这不是一个好的解决方案。*
  • 可以进行切换,并让蓝图创建db实例,然后该应用程序将其与蓝图的其余部分一起导入。但是随后,任何其他希望创建模型的蓝图都需要从蓝图而不是应用程序从导入。

  • 因此,我的问题是:
  • 是否有一种方法可以让蓝图定义模型,而又不知道它们以后将要使用的应用程序-并且有几张蓝图组合在一起?我的意思是必须从您的蓝图导入应用程序模块/软件包。
  • 我从一开始就错了吗?蓝图是否不是要独立于应用程序并可以重新分发(例如Django应用程序)?
  • 如果不是,那么应该使用什么模式来创建类似的东西? flask 扩展?您是否应该简单地做到这一点-也许集中所有模型/方案以及Ruby on Rails?




  • 我被要求提供一个示例,所以让我们做一些简单的事情:假设我有一个描述“扁平化”的蓝图,即“简单”的,存储在数据库中的“静态”内容。它使用仅带有短名称(用于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
    

    这个问题与:
  • Flask-SQLAlchemy import/context issue
  • What's your folder layout for a Flask app divided in modules?

  • 以及其他各种选项,但所有答复似乎都依赖于导入应用程序的db实例,或者相反。 "Large app how to" Wiki页面还使用“以蓝图导入应用程序”模式。
    *由于官方文档显示了如何在蓝图中创建路线, View ,模板和 Assets ,而不关心它在“哪个”应用中,因此我认为,蓝图通常应可在所有应用之间重用。但是,如果没有独立的模型,这种模块化似乎没有什么用。
    由于可以将蓝图多次挂接到应用程序中,因此在蓝图中建立模型可能只是错误的方法?

    最佳答案

    我相信最真实的答案是模块化蓝图不应该直接与数据访问相关,而应该依赖于提供兼容实现的应用程序。

    因此,给出您的示例蓝图。

    from flask import current_app, Blueprint, render_template
    
    flat_pages = Blueprint('flat_pages', __name__, template_folder='templates')
    
    @flat_pages.record
    def record(state):
        db = state.app.config.get("flat_pages.db")
    
        if db is None:
            raise Exception("This blueprint expects you to provide "
                            "database access through flat_pages.db")
    
    @flat_pages.route('/<page>')
    def show(page):
        db = current_app.config["flat_pages.db"]
        page_object = db.find_page_by_name(page)
        return render_template('pages/{}.html'.format(page), page=page_object)
    

    因此,没有什么可以阻止您提供默认实现的。
    def setup_default_flat_pages_db(db):
        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
    
        class FlatPagesDBO(object):
            def find_page_by_name(self, name):
                return Page.query.filter_by(name=name).first()
    
        return FlatPagesDBO()
    

    并在您的配置中。
    app.config["flat_pages.db"] = setup_default_flat_pages_db(db)
    

    通过不依赖于db.Model的直接继承,可以使上面的内容更简洁,而仅使用来自sqlalchemy的vanilla declarative_base,但这应该代表其要点。

    关于python - 在不引用应用程序的情况下在蓝图模型中使用Flask-SQLAlchemy,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13058800/

    10-12 21:11