View decorators¶
Decorators for view handlers.
All items in this module can be imported directly from coaster.views
.
-
exception
coaster.views.decorators.
RequestTypeError
(description: Optional[str] = None, response: Optional[Response] = None)[source]¶ Exception that combines TypeError with BadRequest. Used by
requestargs()
.
-
exception
coaster.views.decorators.
RequestValueError
(description: Optional[str] = None, response: Optional[Response] = None)[source]¶ Exception that combines ValueError with BadRequest. Used by
requestargs()
.
-
coaster.views.decorators.
requestargs
(*args, **config)[source]¶ Decorator that loads parameters from request.values if not specified in the function’s keyword arguments. Usage:
@requestargs('param1', ('param2', int), 'param3[]', ...) def function(param1, param2=0, param3=None): ...
requestargs takes a list of parameters to pass to the wrapped function, with an optional filter (useful to convert incoming string request data into integers and other common types). If a required parameter is missing and your function does not specify a default value, Python will raise TypeError. requestargs recasts this as
RequestTypeError
, which returns HTTP 400 Bad Request.If the parameter name ends in
[]
, requestargs will attempt to read a list from the incoming data. Filters are applied to each member of the list, not to the whole list.If the filter raises a ValueError, this is recast as a
RequestValueError
, which also returns HTTP 400 Bad Request.Tests:
>>> from flask import Flask >>> app = Flask(__name__) >>> >>> @requestargs('p1', ('p2', int), ('p3[]', int)) ... def f(p1, p2=None, p3=None): ... return p1, p2, p3 ... >>> f(p1=1) (1, None, None) >>> f(p1=1, p2=2) (1, 2, None) >>> f(p1='a', p2='b') ('a', 'b', None) >>> with app.test_request_context('/?p2=2'): ... f(p1='1') ... ('1', 2, None) >>> with app.test_request_context('/?p3=1&p3=2'): ... f(p1='1', p2='2') ... ('1', '2', [1, 2]) >>> with app.test_request_context('/?p2=100&p3=1&p3=2'): ... f(p1='1', p2=200) ... ('1', 200, [1, 2])
-
coaster.views.decorators.
requestform
(*args)[source]¶ Like
requestargs()
, but loads from request.form (the form submission).
-
coaster.views.decorators.
requestquery
(*args)[source]¶ Like
requestargs()
, but loads from request.args (the query string).
-
coaster.views.decorators.
load_model
(model, attributes=None, parameter=None, kwargs=False, permission=None, addlperms=None, urlcheck=())[source]¶ Decorator to load a model given a query parameter.
Typical usage:
@app.route('/<profile>') @load_model(Profile, {'name': 'profile'}, 'profileob') def profile_view(profileob): # 'profileob' is now a Profile model instance. # The load_model decorator replaced this: # profileob = Profile.query.filter_by(name=profile).first_or_404() return "Hello, %s" % profileob.name
Using the same name for request and parameter makes code easier to understand:
@app.route('/<profile>') @load_model(Profile, {'name': 'profile'}, 'profile') def profile_view(profile): return "Hello, %s" % profile.name
load_model
aborts with a 404 if no instance is found.Parameters: - model – The SQLAlchemy model to query. Must contain a
query
object (which is the default with Flask-SQLAlchemy) - attributes – A dict of attributes (from the URL request) that will be used to query for the object. For each key:value pair, the key is the name of the column on the model and the value is the name of the request parameter that contains the data
- parameter – The name of the parameter to the decorated function via which the result is passed. Usually the same as the attribute. If the parameter name is prefixed with ‘g.’, the parameter is also made available as g.<parameter>
- kwargs – If True, the original request parameters are passed to the decorated
function as a
kwargs
parameter - permission – If present,
load_model
calls thepermissions()
method of the retrieved object withcurrent_auth.actor
as a parameter. Ifpermission
is not present in the result,load_model
aborts with a 403. The permission may be a string or a list of strings, in which case access is allowed if any of the listed permissions are available - addlperms – Iterable or callable that returns an iterable containing
additional permissions available to the user, apart from those granted by the
models. In an app that uses Lastuser for authentication, passing
lastuser.permissions
will pass through permissions granted via Lastuser - urlcheck (list) – If an attribute in this list has been used to load an object,
but the value of the attribute in the loaded object does not match the request
argument, issue a redirect to the corrected URL. This is useful for attributes
like
url_id_name
andurl_name_uuid_b58
where thename
component may change
- model – The SQLAlchemy model to query. Must contain a
-
coaster.views.decorators.
load_models
(*chain, **kwargs)[source]¶ Decorator to load a chain of models from the given parameters. This works just like
load_model()
and accepts the same parameters, with some small differences.Parameters: - chain – The chain is a list of tuples of (
model
,attributes
,parameter
). Lists and tuples can be used interchangeably. All retrieved instances are passed as parameters to the decorated function - permission – Same as in
load_model()
, exceptpermissions()
is called on every instance in the chain and the retrieved permissions are passed as the second parameter to the next instance in the chain. This allows later instances to revoke permissions granted by earlier instances. As an example, if a URL represents a hierarchy such as/<page>/<comment>
, thepage
can assignedit
anddelete
permissions, while thecomment
can revokeedit
and retaindelete
if the current user owns the page but not the comment
In the following example, load_models loads a Folder with a name matching the name in the URL, then loads a Page with a matching name and with the just-loaded Folder as parent. If the Page provides a ‘view’ permission to the current user, the decorated function is called:
@app.route('/<folder_name>/<page_name>') @load_models( (Folder, {'name': 'folder_name'}, 'folder'), (Page, {'name': 'page_name', 'parent': 'folder'}, 'page'), permission='view') def show_page(folder, page): return render_template('page.html', folder=folder, page=page)
- chain – The chain is a list of tuples of (
-
coaster.views.decorators.
render_with
(template=None, json=False, jsonp=False)[source]¶ Decorator to render the wrapped function with the given template (or dictionary of mimetype keys to templates, where the template is a string name of a template file or a callable that returns a Response). The function’s return value must be a dictionary and is passed to the template as parameters. Callable templates get a single parameter with the function’s return value. Usage:
@app.route('/myview') @render_with('myview.html') def myview(): return {'data': 'value'} @app.route('/myview_with_json') @render_with('myview.html', json=True) def myview_no_json(): return {'data': 'value'} @app.route('/otherview') @render_with({ 'text/html': 'otherview.html', 'text/xml': 'otherview.xml'}) def otherview(): return {'data': 'value'} @app.route('/404view') @render_with('myview.html') def myview(): return {'error': '404 Not Found'}, 404 @app.route('/headerview') @render_with('myview.html') def myview(): return {'data': 'value'}, 200, {'X-Header': 'Header value'}
When a mimetype is specified and the template is not a callable, the response is returned with the same mimetype. Callable templates must return Response objects to ensure the correct mimetype is set.
If a dictionary of templates is provided and does not include a handler for
*/*
, render_with will attempt to use the handler for (in order)text/html
,text/plain
and the various JSON types, falling back to rendering the value into a unicode string.If the method is called outside a request context, the wrapped method’s original return value is returned. This is meant to facilitate testing and should not be used to call the method from within another view handler as the presence of a request context will trigger template rendering.
Rendering may also be suspended by calling the view handler with
_render=False
.render_with provides JSON and JSONP handlers for the
application/json
,text/json
andtext/x-json
mimetypes ifjson
orjsonp
is True (default is False).Parameters: - template – Single template, or dictionary of MIME type to templates. If the template is a callable, it is called with the output of the wrapped function
- json – Helper to add a JSON handler (default is False)
- jsonp – Helper to add a JSONP handler (if True, also provides JSON, default is False)
-
coaster.views.decorators.
cors
(origins, methods=('HEAD', 'OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'), headers=('Accept', 'Accept-Language', 'Content-Language', 'Content-Type', 'X-Requested-With'), max_age=None)[source]¶ Adds CORS headers to the decorated view function.
Parameters: - origins – Allowed origins (see below)
- methods – A list of allowed HTTP methods
- headers – A list of allowed HTTP headers
- max_age – Duration in seconds for which the CORS response may be cached
The
origins
parameter may be one of:- A callable that receives the origin as a parameter.
- A list of origins.
*
, indicating that this resource is accessible by any origin.
Example use:
from flask import Flask, Response from coaster.views import cors app = Flask(__name__) @app.route('/any') @cors('*') def any_origin(): return Response() @app.route('/static', methods=['GET', 'POST']) @cors( ['https://hasgeek.com'], methods=['GET'], headers=['Content-Type', 'X-Requested-With'], max_age=3600) def static_list(): return Response() def check_origin(origin): # check if origin should be allowed return True @app.route('/callable') @cors(check_origin) def callable_function(): return Response()
-
coaster.views.decorators.
requires_permission
(permission)[source]¶ View decorator that requires a certain permission to be present in
current_auth.permissions
before the view is allowed to proceed. Aborts with403 Forbidden
if the permission is not present.The decorated view will have an
is_available
method that can be called to perform the same test.Parameters: permission – Permission that is required. If a collection type is provided, any one permission must be available