Routing

Routing determines how URLs are mapped to view functions. When you create a route, either by calling app.route() or by creating a Route object directly, you have a number of options for controlling which requests are matched by the route and what information is extracted from the request and passed to your view.

Some example routes:

app = FrescoApp()

app.route('/', GET, homepage)
app.route('/login', GET, 'myapp.views.auth.login_form')

app.route('/form', [GET, POST], form_handler)
app.route('/contact', POST, send_message)

app.route('/image/<id:int>.jpg', GET, image,
         name='image-original')

app.route('/image/<id:int>-thumb.jpg', GET, image, size=(100, 100),
          name='image-thumb')

Or using the class-based view syntax:

class Greeter(object):

   __routes__ = [
      Route('/hello', GET, 'sayhello'),
      Route('/bonjour', GET, 'saybonjour'),
   ]

Routes are tried in the order they are defined. If you compose routes using include(), it is best to structure your application so that each set of included routes has a unique prefix so that it stays clear which URLs resolve to which views.

Constructing Routes

Pattern

The pattern argument determines which URL paths will be matched and which won’t.

You can match on fixed paths or paths that include parameters:

Route('/blog/archive', ...)
Route('/blog/archive/<year:int>', ...)

The second route will extract an integer value for year and pass it to the view function as a keyword argument.

Match values from route paths using any of these keywords:

name example Matches
str /users/<username:str> Any string not including the character /
path /files/<filename:path> Any string, which may include the character /
int /orders/<id:int> Any integer
any /<lang:any('fr', 'en')> A string matching one of the listed options

Method

The method parameter tells the route which HTTP methods to respond to. This must be a string or list of strings. You can use the symbolic constants exported by fresco for this:

from fresco import GET, POST

Route('/', GET, show_page)
Route('/', POST, edit_page)
Route('/form', [GET, POST], form_handler)

You can also use keyword arguments to map methods to views:

Route('/login', GET=login_form, POST=login_submit)

View

The view parameter determines the function that will be called to handle the request.

If your view is a normal function, you can specify the view either by passing the function object:

from myapp.views import auth
Route('/login', GET, auth.login_form)

Or using its fully qualified name as a string:

Route('/login', GET, 'myapp.views.auth.login_form')

If you are using class based views, you can substitute the name of the method here as a string. This allows you to declare routes before the view methods have been defined:

class MyViews(object):

   __routes__ = [Route('/', GET, 'myview')]

   def myview(self):
      return Response(...)

Predicate

You can supply a predicate function will be tested before the request is routed to your view:

def auth_cookie_set(request):
   return 'auth' in request.cookies

Route('/', GET, myview, predicate=auth_cookie_set)

Predicate functions must accept a single Request argument and return either True or False (or raise an appropriate ResponseException).

Decorators

You can supply one or more function decorators that will be wrapped around the view function when it is called from your application:

def with_template(template_file):

   def view(*args, **kwargs):
      template_data = func(*args, **kwargs)
      return templating_engine.render(template_file, template_data)
   return view

Route('/', GET, homepage, decorators=[with_template('desktop.html')])
Route('/m', GET, homepage, decorators=[with_template('mobile.html')])

Keyword arguments

Your route definition can contain keyword arguments that are passed through to the view function. For example:

# POST /sales/contact → contact(recipient='sales@example.com')
Route('/sales/contact', POST, contact, recipient='sales@example.com')

# POST /support/contact → contact(recipient='sales@example.com')
Route('/support/contact', POST, contact, recipient='support@example.com')

Be careful though, as some keyword arguments are used by the Route constructor itself. It’s safer to pass keyword arguments as a dict, avoiding any risk of clashes:

Route('/take-payment', GET, payment_form,
      kwargs={'methods': ['creditcard', 'banktransfer']})

Positional arguments

These are similar to keyword arguments as described above. Define them using the args argument to the Route constructor.

This example would cause a positional argument value of 80 to be passed to the image_thumbnail view function:

Route('/image/<id:int>-thumb.jpg', GET, image_thumbnail, args=(80,))

Response filters

The filter() method lets you supply one or more functions to postprocess the output of the view function:

def json_response(data):
    return Response([json.dumps(data)], content_type='application/json')

Route('/', GET, homepage).filter(json_response)

You can also use filter() as a decorator:

@Route.filter(render_with_template, 'index.html')
def homepage():
    return {'message': 'Welcome to my site!'}

app = FrescoApp()
app.route('/', GET, homepage)

For more flexibility, wrap() can wrap the view function inside another function, which can do anything from modifying the view’s input arguments or output, to substituting an entirely different view function.

You can also use wrap() as a function decorator in the same way as filter(). Note that Route.decorate is an alternative name for this function.

Before hooks

before() registers a function to be run before the view function. This function must take the same arguments as the view and may return a response (in which case the view will not be called), or None, in which case the view will be called normally:

def check_logged_in(page):
    if not context.request.environ.get('REMOTE_USER'):
        return Response.forbidden("Please log in to view this content")

def view_page(page):
    ...

app = FrescoApp()
app.route('/pages/<page:str>', GET, view_page).before(check_permssion)

The above example could also be written using a function decorator style:

@Route.before(check_permssion)
def view_page(page):
    ...

app = FrescoApp()
app.route('/pages/<page:str>', GET, view_page)

Note that when using before() the order of execution is:

  • hooks applied via decorators are run first, in the order the decorators are declared. NB this is the opposite order from which decorator functions are called.
  • then hooks added to the route are applied, in the order in which they were added.

Passing request data to the view

Often you would like keyword arguments to be extracted from form submissions or cookies. For example, to read an argument from the POST or GET form data:

from fresco.routeargs import PostArg
Route('/sales/contact', POST, contact, sender=PostArg())

The advantages of writing views this way are:

  • Views have meaningful function signatures. The purpose of def show_bookings(day, user) is clear at a glance, whereas show_bookings(request) requires you to read the implementation to discover how request parameters are used.
  • Views are easier to test. You can usually avoid mocking the full (and potentially slow) request cycle by passing test values directly to the view.
  • Views are easier to reuse. Views can more easily delegate to each other by passing simple objects as arguments, without needing to modify and reparse the request object at each step.

As well as extracting values from submitted form or querystring data, fresco supports converting values to a specific type:

from fresco.routeargs import GetArg

# Convert value to an int
# GET /details?product_id=42 → view_product(product_id=42)
Route('/details', GET, view_product, product_id=GetArg(int))

# Convert to a list of ints
# GET /bookings?day=2&day=3 → show_bookings(day=[2, 3])
Route('/bookings', GET, show_bookings, day=GetArg([int]))

And supplying default values:

Route('/preferences', POST, set_prefs,
      contact_opt_in=PostArg(default=False))

If the user doesn’t provide a value and no default has been specified, BadRequest is raised. You can change the exception class if you want different behaviour:

from fresco.exceptions import NotFound
Route('/details', GET, view_product,
      product_id=GetArg(exception=NotFound))

If your form inputs do not match the names you want in your function signature you can extract from an input with a different name:

# GET /details?id=123 → details(product_id=123)
Route('/details', GET, details, product_id=PostArg(key='id'))

PostArg, GetArg and CookieArg all provide the same interface and allow you to read from the query string, form data (post or get), or cookies respectively.

Passing the entire request or form dictionary

Sometimes it’s useful to pass the entire request to a view. Although you can always access the request data through context.request, you can also explicitly ask the routing system to pass you the raw request object as a function argument:

from fresco.routeargs import RequestObject
Route('/set-language', POST, set_language, request=routeargs.RequestObject())

You can also pass the entire POST data form dictionary to your view:

from fresco.routeargs import PostData
Route('/profile', POST, profile_update, data=PostData())

Other request object parameters

routearg() wraps a custom function to extract arbitrary information from request. For example:

from fresco.routeargs import routearg

Route('/contact', [GET, POST], contact_form,
      method=routearg(lambda r: r.method))

Adding custom route converters

You can match custom expressions in routes by creating a subclass of Converter and decorating it with register_converter():

import collections

from fresco.routing import Converter, register_converter

LatLng = collections.named_tuple('LatLng', 'lat lng')

@register_converter('latlng')
class LatLngConverter(Converter):
    """
    Convert latitude-longitude pairs into a ``LatLng`` named tuple.
    """

    pattern = r'-?\d+(?:\.\d+)?,\-?d+(?:\.\d+)?'

    def from_string(self, s):
        latlng = LatLng(map(float, s.split(',')))

        if -90 <= latlng.lat <= 90 and -180 <= latlng.lng <= 180:
            return latlng
        else:
            raise ValueError(s)

    def to_string(self, latlng):
      return '%s,%s' % latlng

Use the name supplied to register_converter() in your route definitions:

Route('/map/<location:latlng>', GET, view_map)

With this pattern the route will directly pass a LatLng object into your view.

Should from_string raise a ValueError the route is deemed not to have matched and the next route will be tried or a 404 returned if no other route matches. In this case you could use this

Reverse routing - Generating URLs

The urlfor() function generates valid urls given a route name or a reference to a routed function:

from myapp.views import product_details

app = FrescoApp()
app.route('/details/<product_id:int>', GET, product_details)

Calling urlfor(product_details, product_id=7) will now return http://localhost/details/7.

You can also specify the view function as a string, eg:

urlfor('myapp.views.product_details', product_id=7)

context.view_self is a globally available handle on the instance of any class based view, which can simplify URL generation:

urlfor(context.view_self.product_details, product_id=7)

urlfor and view classes

If you only have one instance of your class based view, you can pass either the (unbound) class method or the method name to urlfor(). For example with a setup similar to this:

from myapp.views import BlogViews

app = FrescoApp()
app.include('/blog', BlogViews())

Either of the following will work:

# Generate the URL for the `index` method on the `BlogViews` class
urlfor(BlogViews.index)

# Generate the URL for the `index` method on the `BlogViews` class
# defined in myapp.views
urlfor('myapp.views.BlogViews.index')

If you use the same class view in several routes, you will need a way to distinguish between them when calling urlfor(). If you are generating routes for other views in the same class you can use self or context.view_self and all will be well:

class BlogViews(object):

    def view_post(self, post_id):
        ...
        permalink = urlfor(self.permalink, post_id=post_id)

Or for example from within a template:

<a href="{{ urlfor(context.view_self.blog_index) }}">home</a>

However if you need to generate URLs for other view classes (ie not the current context.view_self), you will need a handle on the view class. One simple pattern is to to keep a handle on your views when you create them:

freds_blog = BlogViews()
company_blog = BlogViews()

app = FrescoApp()
app.include('/fred/blog', freds_blog)
app.include('/blog', company_blog)

Then you can reference the views directly:

from myapp import freds_blog

# Generate the URL for the `index` method on the `freds_blog` object
urlfor(freds_blog.blog_index)

Or by passing the name as a string:

# Generate the URL for the `index` method on the `freds_blog` object
# located in the module `myapp`
urlfor('myapp.freds_blog.blog_index')

Multiple routes, same view

A single view may be routed to multiple URLs. In this case, you must supply a name argument to distinguish them:

from myapp.views import list_users

app = FrescoApp()
app.route('/staff/directory', GET, list_users, role='staff',
          name='staff-directory')
app.route('/student/directory', GET, list_users, role='student',
          name='student-directory')

Now you can specify which route you want by passing the appropriate name to urlfor():

# Will return '/staff/directory'
urlfor('staff-directory')

# Will return '/student/directory'
urlfor('student-directory')

Note that if you call urlfor() with the view function itself, the first configured view will be returned:

# Will return '/staff/directory'
urlfor(list_users)

Default route parameters

You can specify default values for routing parameters by passing a _default argument:

app = FrescoApp()
app.route('/products/<category:str>', GET, user_homepage,
          category_default='all')

You can pass a function if you want this to be generated dynamically. The function will be passed the current request object and should return the value to be used in the URL:

def get_username(request):
    user = request.environ.get('myapp.logged_in_user', None)
    if user:
        return user.username

app = FrescoApp()
app.route('/<username:str>/profile', GET, view_user_profile,
          username_default=get_username)

Including and delegating routes

Fresco currently uses two methods for combining routes together into a single app.

include() copies the routes from another routable object (eg a FrescoApp instance or a module/class with a __routes__ attribute):

class Greeter(object):

   __routes__ = [
      Route('/sayhello', GET, 'sayhello'),
   ]

   def sayhello(self, name):
      return Response(['hello ' + name + '!'])


app = FrescoApp()
app.include('/<name:str>', Greeter())

The delegate() method appears superficially very similar:

app = FrescoApp()
app.delegate('/<name:str>', Greeter())

However instead of including a copy of the object’s routes in your app, it causes a recursive lookup when the base path is matched.

Both of the examples above will respond to URLs like /boris/sayhello and /ken/sayhello, but internally the mechanism is quite different .

If you are not sure whether to use inlcude or delegate, then use include(), this is the simplest and best supported method.

However you should use delegate() if you need to:

  • Use urlfor() to generate URLs for the same routable object exposed at multiple paths.
  • Generate routes dynamically (see below)

delegate() supports a name argument, allowing you to distinguish between multiple copies of the same routeable object:

app.delegate('/london', another_app, name="london")
app.delegate('/paris', another_app, name="paris")

You can then generate URLs using the name as a prefix, eg:

urlfor('london:<route-name>')
urlfor('paris:<route-name>')

It is a limitation of delegate() that you cannot use urlfor without specifying a name prefix.

View classes and inheritance

When subclassing from a view class it’s a common requirement to modify the views.

To add new routes, add them to the base class’s __routes__ attribute:

class UserViews(object):

    __routes__ = [
      Route('/home', GET, 'user_homepage', name='homepage'),
      Route('/orders', GET, 'view_orders'),
      Route('/preferences', GET, 'view_prefs'),
    ]


class AdminUserViews(UserViews):
    __routes__ = UserViews.__routes__ + [
        Route('/dashboard', GET, 'admin_dashboard'),
        Route('/all_orders', GET, 'view_all_orders'),
    ]

This approach is generally not practical if you need to remove or replace existing routes. For this use RouteCollection:

class AdminUserViews(UserViews):
    __routes__ = RouteCollection(UserViews)
    __routes__.remove(UserViews.view_orders)
    __routes__.replace(
        'homepage', Route('/dashboard', GET, 'admin_dashboard'))
    __routes__ += [Route('/all_orders', GET, 'view_all_orders')]

Dynamic routes

delegate() can also allow routes to be constructed dynamically:

class Greeter(object):

   def __init__(self, lang):
      self.lang = lang

   @property
   def __routes__(self):
      if self.lang == 'fr':
         return [Route('/bonjour', GET, self.greet_in_french)]
      else:
         return [Route('/hello', GET, self.greet_in_english)]

   def greet_in_english(self):
      return Response(['hello'])

   def greet_in_french(self):
      return Response(['bonjour'])

app = FrescoApp()
app.delegate("/<lang:any('fr', 'en')>", Greeter, dynamic=True)

Two important points to note here:

  1. The argument to delegate() must be a factory function that returns the routeable object. You can pass the class object (as in this example) or create a custom factory function.
  2. Fresco will call your factory function while traversing routes, passing any arguments parsed from the URL to the factory function.

You can also use route delegation within class based views by using an instance of DelegateRoute

from fresco.routing import Route, DelegateRoute, GET
from myapp.blog import BlogViews

class MyWebApp(object):

   __routes__ = [
      Route('/', GET, 'homepage'),
      DelegateRoute('/blog', BlogViews)
   ]

Using dynamic views to handle common arguments

Very often routes use a similar set of routing args, for example each of the following routes requires a username argument:

app.route('/<username:str>/home', GET, user_homepage)
app.route('/<username:str>/orders', GET, view_orders)
app.route('/<username:str>/preferences', GET, view_prefs)
...

Let’s use a view class to factor out the repeated code:

class UserViews(object):

    __routes__ = [
      Route('/home', GET, 'user_homepage'),
      Route('/orders', GET, 'view_orders'),
      Route('/preferences', GET, 'view_prefs'),
    ]

    def __init__(self, username):
        self.username = username

    def user_homepage(self):
        return Response(['hello %s' % self.username])

We use this in our application with delegate(). By specifying dynamic=True the application will construct a new instance of the class for each request:

app.delegate('/<username:str>', UserViews, dynamic=True)

fresco.routing API reference

class fresco.routing.Pattern[source]

Patterns are matchable against URL paths using their match method. If a path matches, this should return a tuple of (positional_arguments, keyword_arguments) extracted from the URL path. Otherwise this method should return None.

Pattern objects may also be able to take a tuple of (positional_arguments, keyword_arguments) and return a corresponding URL path.

add_prefix(prefix)[source]

Return a copy of the pattern with the given string prepended

match(path)[source]

Should return a tuple of (positional_arguments, keyword_arguments) if the pattern matches the given URL path, or None if it does not match.

path_argument_info()[source]

Return information about the arguments required for pathfor

pathfor(*args, **kwargs)[source]

The inverse of match, this should return a URL path for the given positional and keyword arguments, along with any unused arguments.

Returns:a tuple of (path, remaining_args, remaining_kwargs)
class fresco.routing.Route(pattern, methods=None, view=None, kwargs=None, args=None, name=None, predicate=None, decorators=None, filters=None, **_kwargs)[source]

Represent a URL routing pattern

add_prefix(path)[source]

Return a copy of the Route object with the given path prepended to the routing pattern.

before(func, *args, **kwargs)[source]

Call a function before passing the request to the view.

Route(‘/view-secret-page’, GET, view_secret_page) .before(check_logged_in)
Parameters:
  • func – The function. Must accept the same arguments as the view and may return either None or a Response object. If a response is returned the view will not be invoked.
  • args – Extra positional args to pass to func
  • kwargs – Extra keyword args to pass to func
bindto(instance)[source]

Return copy of the route bound to a given instance.

Use this when traversing view classes.

decorate(decorator, *args, **kwargs)

decorate is an alias for wrap()

filter(func, *args, **kwargs)[source]

Filter the output of the view function through other functions:

Route('/user/<id:int>', GET, edituser)                    .wrap(require_ssl)
        .filter(render, 'user.tmpl')
Parameters:
  • func – The filter function. Must accept the output of the view and return the filtered response
  • args – Extra positional args to pass to func
  • kwargs – Extra keyword args to pass to func
getdecoratedview(view)[source]

Return the view callable decorated with any decorators defined in the route

getview(method)[source]

Return the raw view callable.

path(*args, **kwargs)[source]

Build the path corresponding to this route and return a tuple of:

(<path>, <remaining args>, <remaining kwargs>)

remaining args and remaining kwargs are any values from *args and **kwargs not consumed during path construction.

See also pathfor().

pattern_class

The default class to use for URL pattern matching

alias of ExtensiblePattern

route_keys()[source]

Generate keys by which the route should be indexed

routed_args_default = None

Default values to use for path generation

viewspecs = None

A mapping of HTTP methods to view specifiers

wrap(decorator, *args, **kwargs)[source]

Wrap the view function in a decorator. Can be chained for a fluid api:

Route('/user/<id:int>', GET, edituser)                    .wrap(require_ssl)
        .wrap(logged_in)
class fresco.routing.DelegateRoute(prefix, view, dynamic=False, *args, **kwargs)[source]

A specialisation of Route that is used to delegate a path prefix to another route collection.

class fresco.routing.RouteCollection(routes=None, route_class=None, cache=True)[source]

A collection of Route objects, RouteCollections:

  • Contain methods to configure routes, including the ability to delegate URLs to other RouteCollections
  • Can map from a request to a view
add_prefix(prefix)[source]

Return a copy of the RouteCollection with the given path prepended to all routes.

delegate(path, app, dynamic=False, *args, **kwargs)[source]

Delegate all requests under path to app

Parameters:
  • path – the path prefix at which the app will be available
  • app – a FrescoApp instance
get_routes(path, method, request=None)[source]

Generate routes matching the given path and method:

for rt in routecollection.get_routes('/foo/bar', GET):
    print("Route is", rt.route)
    print("Arguments extracted from the path:", rt.args, rt.kwargs)
    print("RouteCollections are:", rt.collections_traversed)
Parameters:
  • path – the URL path to match (usually this is PATH_INFO)
  • method – the HTTP method to match (usually this is REQUEST_METHOD). May be None, in which case matching will be performed on the path argument only.
  • request – a Request object
Returns:

A generator yielding RouteTraversal objects

include(path, views)[source]

Include a view collection at the given path.

The included view collection’s url properties will be modified to generate the prefixed URLs.

Parameters:
  • path – Path at which to include the views
  • views – Any collection of views (must expose a __routes___ attribute)
max_route_cache_size = 500

The maximum size for the (method, path) => route cache

min_route_cache_size = 20

The minimum size for the (method, path) => route cache

pathfor(viewspec, *args, **kwargs)[source]

Return the path component of the url for the given view name/function spec.

Parameters:viewspec – a view name, a reference in the form 'package.module.viewfunction', or the view callable itself.
remove(viewspec)[source]

Remove the route(s) identified by viewspec

Parameters:viewspec – The routed view callable, or its fully qualified name (‘package.module.view_function’), or the name of a named route
replace(viewspec, newroute)[source]

Replace the route(s) identified by viewspec with a new Route.

Parameters:
  • viewspec – The routed view callable, or its fully qualified name (‘package.module.view_function’), or the name of a named route
  • newroute – The replacement route. This may be None, in which case the route will be removed without replacement
route(pattern, methods=None, view=None, *args, **kwargs)[source]

Match a URL pattern to a view function. Can be used as a function decorator, in which case the view parameter should not be passed.

Parameters:
  • pattern – A string that can be compiled into a path pattern
  • methods – A list of HTTP methods the view is bound to
  • view – The view function. If not specified a function decorator will be returned.

Other parameters are as for the Route constructor.

route_all(path, *args, **kwargs)[source]

Expose a view for all URLs starting with path.

Parameters:path – the path prefix at which the view will be routed
route_class

alias of Route

route_wsgi(path, wsgiapp, rewrite_script_name=True, *args, **kwargs)[source]

Route requests to path to the given WSGI application

Parameters:
  • path – the mount point for the app
  • wsgiapp – the WSGI callable
  • rewrite_script_name – if True (the default), the mount point specified by path will be shifted off PATH_INFO and into the SCRIPT_NAME environ key.
routefor(viewspec)[source]

Return the Route instance associated with viewspec.

Views may have multiple routes bound, in this case the first bound route will always take precedence.

This method does not resolve delegated routes.

Parameters:viewspec – a view callable or a string in the form ‘package.module.viewfunction’
fresco.routing.routefor(viewspec, _app=None)[source]

Convenience wrapper around urlfor().

fresco.routeargs API reference

fresco.routeargs.routearg(func, *args, **kwargs)[source]

Construct a RouteArg instance that calls func with the request object as an argument and passes the return value to the routed view:

def extract_name(req):
    return req.get('name')

Route('/', GET, myview, name=routearg(extract_name))

Additional positional and keyword arguments may be passed, eg:

def name_is(req, *friends):
    return req.get('name') in friends

Route('/', GET, myview, is_a_friend=routearg(name_is, 'fred', 'jim'))
fresco.routeargs.FormArg

FormArg may be used as an alias for PostArg

alias of PostArg

class fresco.routeargs.PostArg(converter=None, key=None, default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Extract a view keyword argument from request.form.

Example:

@app.route('/mul', POST, a=FormArg(int), b=FormArg(int))
def view(a, b):
    return Response(['a * b = %d' % (a * b)])
fresco.routeargs.QueryArg

QueryArg may be used as an alias for GetArg

alias of GetArg

class fresco.routeargs.GetArg(converter=None, key=None, default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Extract a view keyword argument from request.query.

Example:

@app.route('/add', GET, a=QueryArg(int), b=QueryArg(int))
def view(a, b):
    return Response(['a + b = %d' % (a + b)])
class fresco.routeargs.CookieArg(converter=None, key=None, default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Extract a view keyword argument from request.cookies.

Example:

@app.route('/', GET, message=CookieArg(key='msg', default=None))
def view(message, message):
    return Response([message])
class fresco.routeargs.SessionArg(converter=None, key=None, default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Extract a view keyword argument from request.session.

Example:

@app.route('/mul', POST, a=FormArg(int), b=FormArg(int))
def view(a, b):
    return Response(['a * b = %d' % (a * b)])
class fresco.routeargs.RequestObject(default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Make the request object itself available as a view argument.

Example:

@app.route('/form', POST, request=RequestObject())
def view(formdata, request):
    ...
fresco.routeargs.FormData

FormData may be used as an alias for PostData

alias of PostData

class fresco.routeargs.PostData(default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Make the request.form MultiDict available as a view argument.

Example:

@app.route('/form', POST, data=FormData())
def view(formdata, data):
    ...
fresco.routeargs.QueryData

QueryData may be used as an alias for GetData

alias of GetData

class fresco.routeargs.GetData(default=[], exception=<class 'fresco.exceptions.MissingRouteArg'>)[source]

Make the request.form MultiDict available as a view argument.

Example:

@app.route('/form', POST, data=GetData())
def view(formdata, data):
    ...