Re: [flask] Circular Imports and Larger Applications Doc
- Sean Lynch
- 2013-07-16 @ 18:24
I did something similar to John's approach in one of my larger Flask
application, using an application factory.
from flask import Flask, request, redirect
from flask_security import current_user
from werkzeug import import_string
from views import configure_views
from urls import configure_urls
from errors import configure_error_handlers
from extensions import configure_extensions
def create_app(config_name, blueprints=None):
config = import_string('application.config.' + config_name)
app_name = config.APP_NAME or __name__
app = Flask(app_name)
configure_blueprints(app, blueprints or config.BLUEPRINTS)
def configure_app(app, config):
app.config.from_envvar("APP_CONFIG", silent=True) # avaiable in the server
app.config['CONFIG_LOADED'] = app.config.__class__.__name__.lower()
Some of those configure methods reside within the same file as the factory
(__init__.py of the application directory), while others were imported in
without any risk of a circular dependency and I could easily control the
initiation order without a global `app` import floating around. It worked
out well for that project.
On Tue, Jul 16, 2013 at 2:10 PM, Jaime Wyant <email@example.com>wrote:
> I've never thought of doing it that way. I don't see anything immediately
> wrong with doing it like that. However, if you really want to go modular,
> consider using blueprints. It's only a bit more work, but it *really*
> `modularizes` things.
> Blueprints can specify their own static and template directories, so
> everything related to some particular part of your app can be `blueprint`ed.
> For example, suppose you wanted to store all of your `user` related code
> in a User blueprint. You could have a package structure like this:
> blueprints [D=dir]
> user [D]
> user [D]
> Then, inside of blueprints/user/__init__.py, you could define your
> blueprint like so:
> from flask import Blueprint
> user_bp = Blueprint('bp_user', __name__,
> def user_create():
> # .. create a user ..
> To use the blueprint from your app you do:
> from blueprints.user import user_bp
> app = Flask(__name__)
> To access the user_create function you'd use this url (because of
> url_prefix above):
> It's a bit more work, but the modularity and decoupling make it worth the
> effort. I've copied/pasted what the docs mention about blueprints. It's
> well worth the effort.
> Hope it helps,
> - Factor an application into a set of blueprints. This is ideal for
> larger applications; a project could instantiate an application object,
> initialize several extensions, and register a collection of blueprints.
> - Register a blueprint on an application at a URL prefix and/or
> subdomain. Parameters in the URL prefix/subdomain become common view
> arguments (with defaults) across all view functions in the blueprint.
> - Register a blueprint multiple times on an application with different
> URL rules.
> - Provide template filters, static files, templates, and other
> utilities through blueprints. A blueprint does not have to implement
> applications or view functions.
> - Register a blueprint on an application for any of these cases when
> initializing a Flask extension.
> On Tue, Jul 16, 2013 at 12:28 PM, John Hutchison <firstname.lastname@example.org>wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>> So, small question regarding the part of the documentation for flask,
>> specifically on the 'Larger Applications' section. I come from a C/C++
>> background (though I am really enjoying Flask and Python), and while
>> working on my mess of a HTML5 patient tracking system (think electronic
>> medical record but for marketing) I started to move to a more modular
>> design and went to the docs for guidance, I noticed that it advises to
>> do a circular import. Is there any benefit to having the circular
>> import over just calling a function with the views contained and passing
>> Example code: https://gist.github.com/athetius/6010156
>> It works with my project (sadly I am unable to share my actual code as
>> my boss and I are clashing over licensing, I wish to make it open
>> source, he wishes to keep it proprietary)
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v1.4.13 (GNU/Linux)
>> -----END PGP SIGNATURE-----
> "Government does not solve problems; it subsidizes them."
> Ronald Reagan