在蓝图模型中使用Flask-SQLAlchemy而不引用该应用程序 [英] Using Flask-SQLAlchemy in Blueprint models without reference to the app

查看:313
本文介绍了在蓝图模型中使用Flask-SQLAlchemy而不引用该应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Blueprints在Flask中创建一个模块化应用程序。

I'm trying to create a "modular application" in Flask using Blueprints.

然而,在创建模型时,我遇到了引用该应用程序以获取Flask-SQLAlchemy提供的 db -object。我想能够使用一些蓝图与多个应用程序(类似于Django应用程序可以使用),所以这不是一个很好的解决方案。*

When creating models, however, I'm running into the problem of having to reference the app in order to get the db-object provided by Flask-SQLAlchemy. I'd like to be able to use some blueprints with more than one app (similar to how Django apps can be used), so this is not a good solution.*


  • 可以做一个switcharoo,并且Blueprint创建 db 实例,应用程序然后与其他蓝图一起导入。但是,任何其他希望创建模型的蓝图都需要从导入蓝图而不是应用程序。

  • It's possible to do a switcharoo, and have the Blueprint create the db instance, which the app then imports together with the rest of the blueprint. But then, any other blueprint wishing to create models need to import from that blueprint instead of the app.

我的问题是:


  • 有没有办法让蓝图定义模型,而没有意识到他们以后使用的应用程序 - 有几个蓝图聚在一起吗?因此,我的意思是必须从蓝图导入应用程序模块/包。

  • 从一开始我错了吗?蓝图是不是独立于应用程序,并且是可再分发的(àla Django应用程序)?


    • 如果没有,那么您应该使用什么模式来创建类似的东西?烧瓶扩展你应该不会这么做 - 也许集中所有的模型/模式?Ruby on Rails?

    • Is there a way to let Blueprints define models without any awareness of the app they're being used in later -- and have several Blueprints come together? By this, I mean having to import the app module/package from your Blueprint.
    • Am I wrong from the outset? Are Blueprints not meant to be independent of the app and be redistributable (à la Django apps)?
      • If not, then what pattern should you use to create something like that? Flask extensions? Should you simply not do it -- and maybe centralize all models/schemas à la Ruby on Rails?

      编辑:我现在一直在想这个,这可能比Flask更像SQLAlchemy,因为你必须有$声明模型时,c $ c> declarative_base()而且 来自某个地方,无论如何!

      Edit: I've been thinking about this myself now, and this might be more related to SQLAlchemy than Flask because you have to have the declarative_base() when declaring models. And that's got to come from somewhere, anyway!

      也许最好的解决方案是让你的项目的模式定义在一个地方并传播像Ruby on Rails那样。声明式SQLAlchemy类的定义比Django的models.py更像是schema.rb。我想这也会使迁移更容易(从 alembic sqlalchemy-migrate )。

      Perhaps the best solution is to have your project's schema defined in one place and spread it around, like Ruby on Rails does. Declarative SQLAlchemy class definitions are really more like schema.rb than Django's models.py. I imagine this would also make it easier to use migrations (from alembic or 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 中):

      Then, it would be nice to let this blueprint define its own model (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
      






      此问题涉及:


      This question is related to:

      • Flask-SQLAlchemy import/context issue
      • What's your folder layout for a Flask app divided in modules?

      和其他各种,但所有回复似乎都依赖于导入应用程序的 db 实例,或做相反大应用程序如何维基页面也使用

      And various others, but all replies seem to rely on import the app's db instance, or doing the reverse. The "Large app how to" wiki page also uses the "import your app in your blueprint" pattern.

      *由于官方文档显示了如何在Blueprint中创建路线,视图,模板和资产,而无需关心什么应用程序是in,我假设Blueprints应该通常可以跨应用程序重复使用。然而,这种模块化似乎并不适用于没有独立模型的。

      由于Blueprints可以挂钩进入应用程序不止一次,可能只是在蓝图中使用模型的错误方法?

      推荐答案

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

      I believe the truest answer is that modular blueprints shouldn't concern themselves directly with data access, but instead rely on the application providing a compatible implementation.

      所以给出了你的例子蓝图。

      So given your example blueprint.

      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)
      

      从此,没有任何东西阻止您提供默认实现。

      From this, there is nothing preventing you from providing a default implementation.

      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,但这应该代表它的要点。

      The above could be made cleaner by not relying in direct inheritance from db.Model and instead just use a vanilla declarative_base from sqlalchemy, but this should represent the gist of it.

      这篇关于在蓝图模型中使用Flask-SQLAlchemy而不引用该应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆