Flask-LazyViews¶
Flask-LazyViews registers URL routes for Flask application or blueprint in lazy way. Ships with additional support of registering admin views, error handlers, custom static files and rendering Jinja2 templates.
- Based on original snippet from Flask documentation
- Works on Python 2.6, 2.7 and 3.3+
- BSD licensed
- Latest documentation on Read the Docs
- Source, issues and pull requests on GitHub
Installation¶
Use pip to install Flask-LazyViews to your system or virtual environment:
$ pip install Flask-LazyViews
Otherwise you could download source dist from GitHub or PyPI and put
flask_lazyviews directory somewhere to $PYTHONPATH, but this way is not
recommended. Use pip for all good things.
Necessity¶
The main purpose of registering lazy views instead of standard approach of
adding routes by decorating view functions with flask.Flask.route()
decorator is avoiding “Circular Import” errors while organizing code in big
Flask project.
For example, when you have project with structure a like:
project/
+ app.py
+ models.py
+ settings.py
+ views.py
and want to use @app.route decorator you obviously need to import app
instance in views module, but to be sure that these view functions registered
as URL routes for your app you need make back import in app module. So you
actually should make inner import if using application factories or just
import views after global app instance already initialized and maybe
configured. This looks not very Pythonic.
In case of using lazy views you don’t need import your views module when you
instantiate your application, all you need to import LazyViews
instance, init it and add URL routes where view function is a string with valid
Python path. And yes adding view support all other route arguments as
endpoint, methods, etc.
And yes, Flask-LazyViews supports flask.Blueprint instances and have
extra features as registering error handlers, adding admin views, additional
static routes and rendering Jinja2 templates without actual view function.
Neat!
Usage¶
To get started all you need to instaniate LazyViews object after
configuring application:
from flask import Flask
from flask_lazyviews import LazyViews
app = Flask(__name__)
views = LazyViews(app)
Or blueprint:
from flask import Blueprint
blueprint = Blueprint('name', __name__)
views = LazyViews(blueprint)
You can also pass the Flask application or blueprint object later, by calling
init_app() or init_blueprint()
respectfully:
views = LazyViews()
def create_app(name=None, **options):
app = Flask(name or __name__)
app.config.update(options)
views.init_app(app, 'path.to.views') # Full path to views module
...
return app
Or:
def create_blueprint(name, **options):
blueprint = Blueprint(name, __name__, **options)
views.init_blueprint(blueprint, '.views') # Rel path to views module
...
return blueprint
Now you ready to go and start using Flask-LazyViews extension.
Adding URL routes¶
Main feature of Flask-LazyViews extension is adding lazy views (touche) to your Flask application or blueprint.
In most cases lazy view is just a string with full Python path to view
function, like app.views.view, where:
appis name of Python package with your Flask application/blueprintviewsis name of views moduleviewis name of view function
In other adding lazy views are equal to registering routes with
flask.Flask.route() method and it supports all its keyword arguments
as methods, endpoint, etc.
To add lazy view to your application you need to call add()
method:
views.add('/', 'app.views.index')
views.add('/comment/add', 'app.views.add_comment', methods=('GET', 'POST'))
views.add('/page/<int:page_id>', 'app.views.page')
To simplify things and avoid repeating base path to your views, like
app.views above, you could use import_prefix while initializing
LazyViews:
views = LazyViews(app, 'app.views')
After you don’t need to repeat this prefix and could add views as:
views.add('/', 'index')
views.add('/comment/add', 'add_comment', methods=('GET', 'POST'))
views.add('/page/<int:page_id>', 'page')
Registering error handlers¶
Flask application and blueprint has ability to register error handlers to customize
processing HTTP errors. In most cases this handlers are view functions which
take error as first argument, so Flask-LazyViews allows you to add this
error handlers with add_error() method:
views.add_error(404, 'views.not_found')
views.add_error(500, 'views.server_error')
views.add_error(AssertionError, 'views.server_error')
Registering app error handler for Blueprint¶
New in version 0.6.
In addition to registering error handlers for “own” URLs Flask blueprint has
ability to register custom error handler for application. To do
this in Flask-LazyViews, you need to pass app=True to
add_error() method:
views.add_error(401, 'views.not_authorized', app=True)
views.add_error(ValueError, 'views.value_error', app=True)
Adding admin views¶
New in version 0.4.
Flask-Admin is one of the most popular
choices for making CRUD admin panel for Flask application. Flask-LazyViews has
support adding admin views in lazy way as done for plain routes. To do this you
need to call add_admin() method:
views.add_admin('admin.AdminView',
endpoint='app_admin',
name='Custom Admin Page')
Note
Keyword arguments passed to add_admin() method
would be transfer to instantiate admin view.
Important
Adding admin views only works for Flask application and when
flask.ext.admin.base.Admin extension already initialized before
calling add_admin() method.
Additional static routes¶
Changed in version 0.6.
Sometimes you need to create additional static route, for example to serve
favicon.ico in root of your app. To do this you need to call
add_static() method:
views.add_static('/favicon.ico', 'icons/favicon.ico', endpoint='favicon')
You also should pass filename to static handler in defaults dict
(default approach prior to 0.6 version):
views.add_static('/favicon.ico',
defaults={'filename': 'icons/favicon.ico'},
endpoint='favicon')
Rendering Jinja2 templates without view functions¶
New in version 0.6.
Sometimes rendering template don’t require any additional logic in view
function, but you still need to define it. To avoid this you could render
those templates directly with add_template() method:
views.add_template('/', 'index.html', endpoint='index')
You also can pass context to your templates, context could be a plain dict:
views.add_template('/',
'index.html',
context={'DUMMY_CONSTANT': True},
endpoint='index')
Or any callable which returns dict:
from flask import g
def settings_context():
return {'settings': get_user_settings(g.user)}
views.add_template('/settings',
'settings.html',
context=settings_context,
endpoint='settings')
Example¶
Flask-LazyViews ships with simple test application which shows basic principles for using extension.
In case you want to run this application in your local environment you need to bootstrap virtual environment for it and run server as:
$ cd /path/to/Flask-LazyViews
$ make -C testapp/ bootstrap
$ make -C testapp/ server
When done, point your browser to http://127.0.0.1:8303/ to see results.
Note
To bootstrap project bootstrapper should be installed to your system as well as GNU Make.
API¶
-
class
flask_lazyviews.LazyViews(instance=None, import_prefix=None)¶ Main instance for adding lazy views to Flask application or blueprint.
-
__init__(instance=None, import_prefix=None)¶ Initialize
LazyViewsinstance.Basically it requires
apporblueprintinstance as first argument, but you could leave it empty and initialize it later with manually callinit_app()method. It could be helpful, if you want to configureLazyViewsinstance somewhere outside yourapp.pyor for multiple applications.
-
add(url_rule, mixed, **options)¶ Add URL rule to Flask application or blueprint.
mixedcould be a real callable function, or a string Python path to callable view function. Ifmixedis a string, it would be wrapped intoLazyViewinstance.
-
add_admin(mixed, *args, **kwargs)¶ Add admin view if Flask-Admin extension added to application.
Important
This method only works for Flask applications, not blueprints.
-
add_error(code_or_exception, mixed, app=False)¶ Add error handler to Flask application or blueprint.
When passing
app=Truetries to register global app error handler for blueprint.
-
add_static(url_rule, filename=None, **options)¶ Add URL rule for serving static files to Flask app or blueprint.
-
add_template(url_rule, template_name, **options)¶ Render template name with context for given URL rule.
Context should be a plain dict or callable. If callable its result would be passed to
flask.render_template()function.
-
build_import_name(import_name)¶ Prepend import prefix to import name if it earlier defined by user.
-
get_view(mixed)¶ If
mixedvalue is callable it’s our view, else wrap it withflask_lazyviews.utils.LazyViewinstance.
-
init_app(app, import_prefix=None)¶ Configure
LazyViewsinstance, storeapporblueprintinstance and import prefix if any.
-
init_blueprint(blueprint, import_prefix=None)¶ Alias for init app function, cause basically there are no important differences between Flask app and blueprint if we only need to add URL rule.
-
-
class
flask_lazyviews.utils.LazyView(name, *args, **kwargs)¶ Import view function only when necessary.
-
__call__(*args, **kwargs)¶ Make real call to the view.
-
__eq__(other)¶ Check that two lazy view instances have equal import names.
-
__getattribute__(name)¶ Proxify documentation attribute from original view if it could be imported.
-
__init__(name, *args, **kwargs)¶ Initialize
LazyViewinstance for view that would be imported fromnamepath.
-
__ne__(other)¶ Check that two lazy view instances have not equal import names.
-
__repr__()¶ Show custom repr message if view function exists.
-
view¶ Import view from string and cache it to current class instance.
-
Changelog¶
0.6 (2014-08-14)¶
- Render Jinja2 templates for given URL rule via
add_template()method. - Register global app error handler from Blueprint by passing
app=Truetoadd_error()method. - Keep
import_prefixinLazyViewsinstance. - Easify registering additional static routes by auto-adding
filenametodefaultsdict. - Fixes #4. Fix registering multiple routes to same lazy view.
- Move documentation from README to Read the Docs
0.5.1 (2014-01-31)¶
- Fixes #3. Make
LazyViewproxy class lazy again. Fix circullar imports and working outside application context.
0.5 (2013-12-27)¶
- Python 3 support (only for Flask 0.10+).
- Flask 0.10+ support.
- Fixes #2. Access view function documentation and repr while loading views via strings.
0.4 (2012-10-28)¶
- Add support of adding admin views to Flask applications via
add_admin()method. - Configure Travis CI support.
0.3 (2012-10-04)¶
- Implement
add_error()shortcut method for adding custom error handling for Flask application or blueprint.
0.2 (2012-09-17)¶
- Implement
init_app()andinit_blueprint()methods for configuringLazyViewsinstance outside main application module or for multiple applications. - Add
add_static()shortcut method for adding custom URL rules for serving static files. - Add ability to register real view functions with
LazyViewsinstance.
0.1 (2012-04-03)¶
- Initial release.
