librelist archives

« back to archive

Circular Imports and Larger Applications Doc

Circular Imports and Larger Applications Doc

From:
John Hutchison
Date:
2013-07-16 @ 17:28
-----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
app?

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)

iQIcBAEBAgAGBQJR5YLBAAoJEHQt1m/4J1JBTBYP/RYGLl3pYDOrLTgL/8vCkx31
Fp8QfX8tgD1BffBbiE9OGBHYNB2sV9X0Ht0qhD83vDRIMCuALDep+OpzH5jwqYb6
x7rqe5VRp0npWJlwWyyTsAnNTMRUpSjRRskfyWYmo0aaJ6SY9PAm2ObFQ2VqwTDm
E+A+HdG8o3EbfiFRiOkpY/wmrXMHniEDmtBJXmcEXRk/GwzFlktXbUPQewyGZKur
wKGhoNlSfnpyWyu0Xc00CBO6XjEu+JpuSuk7HSKrewOa1kFKh8059Z9PQuMp6oXG
iEM21a2zTsEkpmutL91Yci3bwsb6j77aEj7S9CbRLQ0y5gVZXmm/St99yKNZmPrz
qK5cuEGinSEFpJRx1S74QKl3WPbmhw55uQ6rUF6x7CaR3xcbiLFjSc/0epJiBBLo
HhYRLEnDP65eAsOd4IZZXxDmDdUxj4MmK3J3+FoZrHIx9ewMMWPMJrO1CUdHVEEP
a8jVJ31UHf/YaW9K5u36DO3cnWSyiZnpr8Rywkj3708H47n3eusD8razVtbVf+US
N19D6gqGkw4ISCfqnu47Re0xyEOmBO3Ozwh7lKBPoUlQrsEcfCc2PBEKU3vNwbHj
jY5IjsypssO9GScclXfPKvCtbsZMtC4ENrgElRSxkFv9182c/hDQpgQOKVBBOMz8
RkT5A7bBd4arbZOJtW9b
=/Qmd
-----END PGP SIGNATURE-----

Re: [flask] Circular Imports and Larger Applications Doc

From:
Jaime Wyant
Date:
2013-07-16 @ 18:10
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]
    __init__.py
    user [D]
        __init__.py
        static[D]
            userstuff.js
        templates[D]
            user [D]
                create.jinja2
                update.jinja2
                delete.jinja2


Then, inside of blueprints/user/__init__.py, you could define your
blueprint like so:

from flask import Blueprint
user_bp = Blueprint('bp_user', __name__,
                    template_folder='templates',
                    static_folder='static',
                    url_prefix='/user')

@user_bp.route('/create')
def user_create():
    # .. create a user ..


To use the blueprint from your app you do:
from blueprints.user import user_bp

app = Flask(__name__)
app.register_blueprint(user_bp)

To access the user_create function you'd use this url (because of
url_prefix above):

/user/create

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,
jw


   - 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 <sollux@athetius.com>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
> app?
>
> 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)
>
> iQIcBAEBAgAGBQJR5YLBAAoJEHQt1m/4J1JBTBYP/RYGLl3pYDOrLTgL/8vCkx31
> Fp8QfX8tgD1BffBbiE9OGBHYNB2sV9X0Ht0qhD83vDRIMCuALDep+OpzH5jwqYb6
> x7rqe5VRp0npWJlwWyyTsAnNTMRUpSjRRskfyWYmo0aaJ6SY9PAm2ObFQ2VqwTDm
> E+A+HdG8o3EbfiFRiOkpY/wmrXMHniEDmtBJXmcEXRk/GwzFlktXbUPQewyGZKur
> wKGhoNlSfnpyWyu0Xc00CBO6XjEu+JpuSuk7HSKrewOa1kFKh8059Z9PQuMp6oXG
> iEM21a2zTsEkpmutL91Yci3bwsb6j77aEj7S9CbRLQ0y5gVZXmm/St99yKNZmPrz
> qK5cuEGinSEFpJRx1S74QKl3WPbmhw55uQ6rUF6x7CaR3xcbiLFjSc/0epJiBBLo
> HhYRLEnDP65eAsOd4IZZXxDmDdUxj4MmK3J3+FoZrHIx9ewMMWPMJrO1CUdHVEEP
> a8jVJ31UHf/YaW9K5u36DO3cnWSyiZnpr8Rywkj3708H47n3eusD8razVtbVf+US
> N19D6gqGkw4ISCfqnu47Re0xyEOmBO3Ozwh7lKBPoUlQrsEcfCc2PBEKU3vNwbHj
> jY5IjsypssO9GScclXfPKvCtbsZMtC4ENrgElRSxkFv9182c/hDQpgQOKVBBOMz8
> RkT5A7bBd4arbZOJtW9b
> =/Qmd
> -----END PGP SIGNATURE-----
>



-- 
"Government does not solve problems; it subsidizes them."
Ronald Reagan

Re: [flask] Circular Imports and Larger Applications Doc

From:
Sean Lynch
Date:
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
import models


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_app(app, config)
    configure_blueprints(app, blueprints or config.BLUEPRINTS)
    configure_database(app)
    configure_extensions(app)
    configure_context_processors(app)
    configure_template_filters(app)
    configure_before_request(app)
    configure_error_handlers(app)
    configure_views(app)
    configure_urls(app)

    return app

def configure_app(app, config):
    app.config.from_object(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 <programmer.py@gmail.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]
>     __init__.py
>     user [D]
>         __init__.py
>         static[D]
>             userstuff.js
>         templates[D]
>             user [D]
>                 create.jinja2
>                 update.jinja2
>                 delete.jinja2
>
>
> Then, inside of blueprints/user/__init__.py, you could define your
> blueprint like so:
>
> from flask import Blueprint
> user_bp = Blueprint('bp_user', __name__,
>                     template_folder='templates',
>                     static_folder='static',
>                     url_prefix='/user')
>
> @user_bp.route('/create')
> def user_create():
>     # .. create a user ..
>
>
> To use the blueprint from your app you do:
> from blueprints.user import user_bp
>
> app = Flask(__name__)
> app.register_blueprint(user_bp)
>
> To access the user_create function you'd use this url (because of
> url_prefix above):
>
> /user/create
>
> 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,
> jw
>
>
>    - 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 <sollux@athetius.com>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
>> app?
>>
>> 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)
>>
>> iQIcBAEBAgAGBQJR5YLBAAoJEHQt1m/4J1JBTBYP/RYGLl3pYDOrLTgL/8vCkx31
>> Fp8QfX8tgD1BffBbiE9OGBHYNB2sV9X0Ht0qhD83vDRIMCuALDep+OpzH5jwqYb6
>> x7rqe5VRp0npWJlwWyyTsAnNTMRUpSjRRskfyWYmo0aaJ6SY9PAm2ObFQ2VqwTDm
>> E+A+HdG8o3EbfiFRiOkpY/wmrXMHniEDmtBJXmcEXRk/GwzFlktXbUPQewyGZKur
>> wKGhoNlSfnpyWyu0Xc00CBO6XjEu+JpuSuk7HSKrewOa1kFKh8059Z9PQuMp6oXG
>> iEM21a2zTsEkpmutL91Yci3bwsb6j77aEj7S9CbRLQ0y5gVZXmm/St99yKNZmPrz
>> qK5cuEGinSEFpJRx1S74QKl3WPbmhw55uQ6rUF6x7CaR3xcbiLFjSc/0epJiBBLo
>> HhYRLEnDP65eAsOd4IZZXxDmDdUxj4MmK3J3+FoZrHIx9ewMMWPMJrO1CUdHVEEP
>> a8jVJ31UHf/YaW9K5u36DO3cnWSyiZnpr8Rywkj3708H47n3eusD8razVtbVf+US
>> N19D6gqGkw4ISCfqnu47Re0xyEOmBO3Ozwh7lKBPoUlQrsEcfCc2PBEKU3vNwbHj
>> jY5IjsypssO9GScclXfPKvCtbsZMtC4ENrgElRSxkFv9182c/hDQpgQOKVBBOMz8
>> RkT5A7bBd4arbZOJtW9b
>> =/Qmd
>> -----END PGP SIGNATURE-----
>>
>
>
>
> --
> "Government does not solve problems; it subsidizes them."
> Ronald Reagan
>