Blueprints and Extensions and SQLAlchemy #289

Open
mitsuhiko opened this Issue Jul 30, 2011 · 7 comments

Comments

9 participants
Owner

mitsuhiko commented Jul 30, 2011

We do not encourage people to create more than one database connection and to connect to databases in arbitrary extensions. The obvious exception are extensions whose sole purpose is to connect to databases. Dependency resolving is done by the developer. Eg:

app = Flask(__name__)
db = SQLAlchemy(app)
something = SomethingElse(app, db)

The problem comes with blueprints. If SomethingElse wants to define models it has to do that at a local scope where it has the reference to the db. Assuming it provides blueprints, how does the blueprint's views and other code get to the models? The sad truth is that if you make up blueprints on the fly the views in that blueprint don't know how to reference it.

Contributor

mrjoes commented Jul 30, 2011

It depends from the use case.

I have following assumptions:

  1. Application might want to access blueprint models
  2. There can be more than one instance of the blueprint, so there can be multiple instances of the same model mapped to different or same database table(s) (using prefixed table name, etc)
  3. Blueprints don't know how they're going to be used in the application - all parameters are passed in object creation time
  4. Which brings to the point - blueprints should always dynamicly create their models based on the input parameters to the constructor

For #1, snippet can look like:
something.MyModel.query.all()

I came across this issue with my bugLink project (http://buglink.readthedocs.org/), where the basic app knows about the relationship changeset <-> issue, and extensions to the app should provide release <-> build <-> changeset ( <-> issue).

My understanding of this is that Blueprint are intended to extend the views. If you need to extend the model, you need to define something like a YellowPrint. As the model is highly coupled with the controller, YellowPrint could also have some mechanism in place to extend your controller. But there is no point in extending the controller if you don't make use of the extension provided. Here we come back to the views. Which brings us to the GreenPrint if you need to extend the views and the model.

Contributor

jfinkels commented Apr 5, 2012

I don't know if this is exactly the situation you are describing, but I have something that looks like this in Flask-Restless. Check out http://readthedocs.org/docs/flask-restless/en/latest/quickstart.html

Nice work!

@untitaker untitaker modified the milestone: 0.9 Oct 7, 2014

@untitaker untitaker removed the 0.8 label Oct 7, 2014

@untitaker untitaker modified the milestones: 0.9, 1.0, 0.11 Apr 25, 2015

@davidism davidism self-assigned this Oct 30, 2015

Owner

davidism commented Oct 30, 2015

There are a few solutions I've seen, depending on the use case:

  • Inject dependencies and explicitly generate the views. This use is a good use case for class based views. During init_app, the extension generates the models and passes them to as_view. This is similar to what @jfinkels mentions.
  • Provide abstract bases for the models, and expect the user to subclass them and use callbacks to set proxies. Flask-Login does this with UserMixin, login_manager.user_loader, and current_user. This is useful when
  • Set properties on the extension instance, then pull them from current_app.extensions['my_ext'].MyModel in views. I don't have an example off the top of my head, but this is a similar concept to Flask-Login's login_manager.anonymous_user.

I'll work on some short examples for each of these solutions to add to the docs on extensions.

@davidism davidism modified the milestones: 1.0, 0.11 Jun 1, 2016

@davidism davidism removed the feedback label Apr 19, 2017

Contributor

kennethreitz commented May 25, 2017

Closing as this issue is OLD.

Contributor

kennethreitz commented May 25, 2017

keeping open as this seems important

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment