diff options
Diffstat (limited to 'app/static/doc/flask-docs/_sources/patterns/viewdecorators.txt')
-rw-r--r-- | app/static/doc/flask-docs/_sources/patterns/viewdecorators.txt | 168 |
1 files changed, 0 insertions, 168 deletions
diff --git a/app/static/doc/flask-docs/_sources/patterns/viewdecorators.txt b/app/static/doc/flask-docs/_sources/patterns/viewdecorators.txt deleted file mode 100644 index a094857..0000000 --- a/app/static/doc/flask-docs/_sources/patterns/viewdecorators.txt +++ /dev/null @@ -1,168 +0,0 @@ -View Decorators -=============== - -Python has a really interesting feature called function decorators. This -allow some really neat things for web applications. Because each view in -Flask is a function decorators can be used to inject additional -functionality to one or more functions. The :meth:`~flask.Flask.route` -decorator is the one you probably used already. But there are use cases -for implementing your own decorator. For instance, imagine you have a -view that should only be used by people that are logged in to. If a user -goes to the site and is not logged in, they should be redirected to the -login page. This is a good example of a use case where a decorator is an -excellent solution. - -Login Required Decorator ------------------------- - -So let's implement such a decorator. A decorator is a function that -returns a function. Pretty simple actually. The only thing you have to -keep in mind when implementing something like this is to update the -`__name__`, `__module__` and some other attributes of a function. This is -often forgotten, but you don't have to do that by hand, there is a -function for that that is used like a decorator (:func:`functools.wraps`). - -This example assumes that the login page is called ``'login'`` and that -the current user is stored as `g.user` and `None` if there is no-one -logged in:: - - from functools import wraps - from flask import g, request, redirect, url_for - - def login_required(f): - @wraps(f) - def decorated_function(*args, **kwargs): - if g.user is None: - return redirect(url_for('login', next=request.url)) - return f(*args, **kwargs) - return decorated_function - -So how would you use that decorator now? Apply it as innermost decorator -to a view function. When applying further decorators, always remember -that the :meth:`~flask.Flask.route` decorator is the outermost:: - - @app.route('/secret_page') - @login_required - def secret_page(): - pass - -Caching Decorator ------------------ - -Imagine you have a view function that does an expensive calculation and -because of that you would like to cache the generated results for a -certain amount of time. A decorator would be nice for that. We're -assuming you have set up a cache like mentioned in :ref:`caching-pattern`. - -Here an example cache function. It generates the cache key from a -specific prefix (actually a format string) and the current path of the -request. Notice that we are using a function that first creates the -decorator that then decorates the function. Sounds awful? Unfortunately -it is a little bit more complex, but the code should still be -straightforward to read. - -The decorated function will then work as follows - -1. get the unique cache key for the current request base on the current - path. -2. get the value for that key from the cache. If the cache returned - something we will return that value. -3. otherwise the original function is called and the return value is - stored in the cache for the timeout provided (by default 5 minutes). - -Here the code:: - - from functools import wraps - from flask import request - - def cached(timeout=5 * 60, key='view/%s'): - def decorator(f): - @wraps(f) - def decorated_function(*args, **kwargs): - cache_key = key % request.path - rv = cache.get(cache_key) - if rv is not None: - return rv - rv = f(*args, **kwargs) - cache.set(cache_key, rv, timeout=timeout) - return rv - return decorated_function - return decorator - -Notice that this assumes an instantiated `cache` object is available, see -:ref:`caching-pattern` for more information. - - -Templating Decorator --------------------- - -A common pattern invented by the TurboGears guys a while back is a -templating decorator. The idea of that decorator is that you return a -dictionary with the values passed to the template from the view function -and the template is automatically rendered. With that, the following -three examples do exactly the same:: - - @app.route('/') - def index(): - return render_template('index.html', value=42) - - @app.route('/') - @templated('index.html') - def index(): - return dict(value=42) - - @app.route('/') - @templated() - def index(): - return dict(value=42) - -As you can see, if no template name is provided it will use the endpoint -of the URL map with dots converted to slashes + ``'.html'``. Otherwise -the provided template name is used. When the decorated function returns, -the dictionary returned is passed to the template rendering function. If -`None` is returned, an empty dictionary is assumed, if something else than -a dictionary is returned we return it from the function unchanged. That -way you can still use the redirect function or return simple strings. - -Here the code for that decorator:: - - from functools import wraps - from flask import request - - def templated(template=None): - def decorator(f): - @wraps(f) - def decorated_function(*args, **kwargs): - template_name = template - if template_name is None: - template_name = request.endpoint \ - .replace('.', '/') + '.html' - ctx = f(*args, **kwargs) - if ctx is None: - ctx = {} - elif not isinstance(ctx, dict): - return ctx - return render_template(template_name, **ctx) - return decorated_function - return decorator - - -Endpoint Decorator ------------------- - -When you want to use the werkzeug routing system for more flexibility you -need to map the endpoint as defined in the :class:`~werkzeug.routing.Rule` -to a view function. This is possible with this decorator. For example:: - - from flask import Flask - from werkzeug.routing import Rule - - app = Flask(__name__) - app.url_map.add(Rule('/', endpoint='index')) - - @app.endpoint('index') - def my_index(): - return "Hello world" - - - |