Controller Bundle API

flask_unchained.bundles.controller

ControllerBundle

The Controller Bundle.

flask_unchained.bundles.controller.config

Config

Default configuration options for the controller bundle.

flask_unchained.bundles.controller.controller

Controller

Base class for views.

flask_unchained.bundles.controller.decorators

param_converter

Convert arguments from the URL and/or query string.

route

Decorator to set default route rules for a view function.

no_route

Decorator to mark a Controller or Resource method as not a route.

flask_unchained.bundles.controller.hooks

RegisterBlueprintsHook

Registers legacy Flask blueprints with the app.

RegisterBundleBlueprintsHook

Registers a bundle blueprint for each bundle with views and/or template/static folders.

RegisterRoutesHook

Registers routes.

flask_unchained.bundles.controller.resource

Resource

Base class for resources.

flask_unchained.bundles.controller.route

Route

This is a semi-private class that you most likely shouldn’t use directly.

flask_unchained.bundles.controller.routes

controller

This function is used to register a controller class’s routes.

resource

This function is used to register a Resource’s routes.

func

This function allows to register legacy view functions as routes, eg.

include

Include the routes from another module at that point in the tree.

prefix

Sets a prefix on all of the child routes passed to it.

rule

Used to specify customizations to the route settings of class-based view function.

get

Like rule(), except specifically for HTTP GET requests.

patch

Like rule(), except specifically for HTTP PATCH requests.

post

Like rule(), except specifically for HTTP POST requests.

put

Like rule(), except specifically for HTTP PUT requests.

delete

Like rule(), except specifically for HTTP DELETE requests.

flask_unchained.bundles.controller.utils

redirect

An improved version of flask’s redirect function

url_for

An improved version of flask’s url_for function

abort

Raises an HTTPException for the given status code or WSGI application.

generate_csrf

Generate a CSRF token.

ControllerBundle

class flask_unchained.bundles.controller.ControllerBundle[source]

The Controller Bundle.

name: str = 'controller_bundle'

The name of the Controller Bundle.

endpoints: Dict[str, List[Route]] = None

Lookup of routes by endpoint name.

controller_endpoints: Dict[str, List[Route]] = None

Lookup of routes by keys: f’{ControllerClassName}.{view_method_name}’

bundle_routes: Dict[str, List[Route]] = None

Lookup of routes belonging to each bundle by bundle name.

other_routes: List[Route] = None

List of routes not associated with any bundles.

before_init_app(app: flask_unchained.flask_unchained.FlaskUnchained)[source]

Configure the Jinja environment and template loader.

Config

class flask_unchained.bundles.controller.config.Config[source]

Default configuration options for the controller bundle.

FLASH_MESSAGES = True

Whether or not to enable flash messages.

NOTE: This only works for messages flashed using the flask_unchained.Controller.flash() method; using the flask.flash() function directly will not respect this setting.

TEMPLATE_FILE_EXTENSION = '.html'

The default file extension to use for templates.

WTF_CSRF_ENABLED = False

Whether or not to enable CSRF protection.

Views

Controller

class flask_unchained.Controller[source]

Base class for views.

Concrete controllers should subclass this and their public methods will used as the views. By default view methods will be assigned routing defaults with the HTTP method GET and paths as the kebab-cased method name. For example:

from flask_unchained import Controller, injectable, route, no_route
from flask_unchained.bundles.sqlalchemy import SessionManager

class SiteController(Controller):
    class Meta:
        abstract = False  # this is the default; no need to set explicitly
        decorators = ()  # a list of decorators to apply to all view methods
                         # on the controller (defaults to an empty tuple)
        template_folder = 'site'  # defaults to the snake_cased class name,
                                  # minus any Controller/View suffix
        template_file_extension = app.config.TEMPLATE_FILE_EXTENSION = '.html'
        url_prefix = None  # optional url prefix to use for all routes
        endpoint_prefix = 'site_controller'  # defaults to snake_cased class name

    # dependency injection works automatically on controllers
    session_manager: SessionManager = injectable

    @route('/')  # change the default path of '/index' to '/'
    def index():
        return self.render('index')  # site/index.html

    # use the defaults, equivalent to @route('/about-us', methods=['GET'])
    def about_us():
        return self.render('about_us.html')  # site/about_us.html

    # change the path, HTTP methods, and the endpoint
    @route('/contact', methods=['GET', 'POST'], endpoint='site_controller.contact')
    def contact_us():
        # ...
        return self.render('site/contact.html.j2')  # site/contact.html.j2

    @no_route
    def public_utility_method():
        return 'not a view'

    def _protected_utility_method():
        return 'not a view'

How do the calls to render know which template to use? They look in Bundle.template_folder for a folder with the controller’s Meta.template_folder and a file with the passed name and Meta.template_file_extension. For example:

class SiteController(Controller):
    # these defaults are automatically determined, unless you override them
    class Meta:
        template_folder = 'site'  # snake_cased class name (minus Controller suffix)
        template_file_extension = '.html'  # from Config.TEMPLATE_FILE_EXTENSION

    def about_us():
        return self.render('about_us')  # site/about_us.html

    def contact():
        return self.render('contact')  # site/contact.html

    def index():
        return self.render('index')  # site/index.html

# your_bundle_root
├── __init__.py
├── templates
│   └── site
│       ├── about_us.html
│       ├── contact.html
│       └── index.html
└── views
    └── site_controller.py
flash(msg: str, category: Optional[str] = None)[source]

Convenience method for flashing messages.

Parameters
  • msg – The message to flash.

  • category – The category of the message.

render(template_name: str, **ctx)[source]

Convenience method for rendering a template.

Parameters
  • template_name – The template’s name. Can either be a full path, or a filename in the controller’s template folder. (The file extension can be omitted.)

  • ctx – Context variables to pass into the template.

redirect(where: Optional[str] = None, default: Optional[str] = None, override: Optional[str] = None, **url_kwargs)[source]

Convenience method for returning redirect responses.

Parameters
  • where – A method name from this controller, a URL, an endpoint, or a config key name to redirect to.

  • default – A method name from this controller, a URL, an endpoint, or a config key name to redirect to if where is invalid.

  • override – Explicitly redirect to a method name from this controller, a URL, an endpoint, or a config key name (takes precedence over the next value in query strings or forms)

  • url_kwargs – the variable arguments of the URL rule

  • _anchor – if provided this is added as anchor to the URL.

  • _external – if set to True, an absolute URL is generated. Server address can be changed via SERVER_NAME configuration variable which defaults to localhost.

  • _external_host – if specified, the host of an external server to generate urls for (eg https://example.com or localhost:8888)

  • _method – if provided this explicitly specifies an HTTP method.

  • _scheme – a string specifying the desired URL scheme. The _external parameter must be set to True or a ValueError is raised. The default behavior uses the same scheme as the current request, or PREFERRED_URL_SCHEME from the app configuration if no request context is available. As of Werkzeug 0.10, this also can be set to an empty string to build protocol-relative URLs.

jsonify(data: Any, code: Union[int, Tuple[int, str, str]] = <HTTPStatus.OK: 200>, headers: Optional[Dict[str, str]] = None)[source]

Convenience method to return json responses.

Parameters
  • data – The python data to jsonify.

  • code – The HTTP status code to return.

  • headers – Any optional headers.

errors(errors: List[str], code: Union[int, Tuple[int, str, str]] = <HTTPStatus.BAD_REQUEST: 400>, key: str = 'errors', headers: Optional[Dict[str, str]] = None)[source]

Convenience method to return errors as json.

Parameters
  • errors – The list of errors.

  • code – The HTTP status code.

  • key – The key to return the errors under.

  • headers – Any optional headers.

after_this_request(fn)[source]

Register a function to run after this request.

Parameters

fn – The function to run. It should accept one argument, the response, which it should also return

Resource

class flask_unchained.Resource[source]

Base class for resources. This is intended for building RESTful APIs. Following the rules shown below, if the given class method is defined, this class will automatically set up the shown routing rule for it.

HTTP Method

Resource class method name

URL Rule

GET

list

/

POST

create

/

GET

get

/<cls.Meta.member_param>

PATCH

patch

/<cls.Meta.member_param>

PUT

put

/<cls.Meta.member_param>

DELETE

delete

/<cls.Meta.member_param>

So, for example:

from flask_unchained import Resource, injectable, param_converter
from flask_unchained.bundles.security import User, UserManager


class UserResource(Resource):
    class Meta:
        member_param: '<string:username>'

    user_manager: UserManager = injectable

    def list():
        return self.jsonify(dict(users=self.user_manager.all()))
        # NOTE: returning SQLAlchemy models directly like this is
        # only supported by ModelResource from the API Bundle

    def create():
        user = self.user_manager.create(**data, commit=True)
        return self.jsonify(dict(user=user), code=201)

    @param_converter(username=User)
    def get(user):
        return self.jsonify(dict(user=user)

    @param_converter(username=User)
    def patch(user):
        user = self.user_manager.update(user, **data, commit=True)
        return self.jsonify(dict(user=user))

    @param_converter(username=User)
    def put(user):
        user = self.user_manager.update(user, **data, commit=True)
        return self.jsonify(dict(user=user))

    @param_converter(username=User)
    def delete(user):
        self.user_manager.delete(user, commit=True)
        return self.make_response('', code=204)

Registered like so:

routes = lambda: [
    resource('/users', UserResource),
]

Would register the following routes:

GET     /users                      UserResource.list
POST    /users                      UserResource.create
GET     /users/<string:username>    UserResource.get
PATCH   /users/<string:username>    UserResource.patch
PUT     /users/<string:username>    UserResource.put
DELETE  /users/<string:username>    UserResource.delete

See also ModelResource from the API bundle.

View Decorators

param_converter

flask_unchained.param_converter(*decorator_args, **decorator_kwargs)[source]

Convert arguments from the URL and/or query string.

For parsing arguments from the query string, pass their names as keyword argument keys where the value is a lookup (dict, Enum) or callable used to convert the query string argument’s value:

@route('/users/<int:id>')
@param_converter(id=User, foo=str, optional=int)
def show_user(user, foo, optional=10):
    # GET /users/1?foo=bar
    # calls show_user(user=User.query.get(1), foo='bar')

It also supports loading SQLAlchemy models from the database. Call with the url parameter names as keyword argument keys, their values being the model class to convert to.

Models will be looked up by the url param names. If a url param name is prefixed with the snake_cased model name, the prefix will be stripped. If a model isn’t found, abort with a 404.

The view function’s argument names must match the snake_cased model names.

For example:

@route('/users/<int:user_id>/posts/<int:id>')
@param_converter(user_id=User, id=Post)
def show_post(user, post):
    # the param converter does the database lookups:
    # user = User.query.get(id=user_id)
    # post = Post.query.get(id=id)
    # and calls the decorated view: show_post(user, post)

# or to customize the argument names passed to the view:
@route('/users/<int:user_id>/posts/<int:post_id>')
@param_converter(user_id={'user_arg_name': User},
                 post_id={'post_arg_name': Post})
def show_post(user_arg_name, post_arg_name):
    # do stuff

route

flask_unchained.route(rule=None, blueprint=None, defaults=None, endpoint=None, is_member=False, methods=None, only_if=<py_meta_utils._missing object>, **rule_options)[source]

Decorator to set default route rules for a view function. The arguments this function accepts are very similar to Flask’s route(), however, the is_member perhaps deserves an example:

class UserResource(ModelResource):
    class Meta:
        model = User
        member_param = '<int:id>'
        include_methods = ['list', 'get']

    @route(is_member=True, methods=['POST'])
    def set_profile_pic(user):
        # do stuff

# registered like so in your ``app_bundle/routes.py``:
routes = lambda: [
    resource(UserResource),
]

# results in the following routes:
# UserResource.list             => GET  /users
# UserResource.get              => GET  /users/<int:id>
# UserResource.set_profile_pic  => POST /users/<int:id>/set-profile-pic
Parameters
  • rule – The URL rule.

  • defaults – Any default values for parameters in the URL rule.

  • endpoint – The endpoint name of this view. Determined automatically if left unspecified.

  • is_member – Whether or not this view is for a Resource member method.

  • methods – A list of HTTP methods supported by this view. Defaults to ['GET'].

  • only_if – A boolean or callable to dynamically determine whether or not to register this route with the app.

  • rule_options – Other kwargs passed on to Rule.

no_route

flask_unchained.no_route(arg=None)[source]

Decorator to mark a Controller or Resource method as not a route. For example:

class SiteController(Controller):
    @route('/')
    def index():
        return self.render('index')

    def about():
        return self.render('about', stuff=self.utility_method())

    @no_route
    def utility_method():
        return 'stuff'

# registered like so in ``your_app_bundle/routes.py``
routes = lambda: [
    controller(SiteController),
]

# results in the following routes
SiteController.index            => GET /
SiteController.about            => GET /about

# but without the @no_route decorator, it would have also added this route:
SiteController.utility_method   => GET /utility-method

NOTE: The perhaps more Pythonic way to accomplish this is to make all non-route methods protected by prefixing them with an underscore, eg _utility_method.

Declarative Routing

controller

flask_unchained.controller(url_prefix_or_controller_cls: Union[str, Type[flask_unchained.bundles.controller.controller.Controller]], controller_cls: Optional[Type[flask_unchained.bundles.controller.controller.Controller]] = None, *, rules: Optional[Iterable[Union[flask_unchained.bundles.controller.route.Route, Iterable[flask_unchained.bundles.controller.route.Route]]]] = None) → Iterable[flask_unchained.bundles.controller.route.Route][source]

This function is used to register a controller class’s routes.

Example usage:

routes = lambda: [
    controller(SiteController),
]

Or with the optional prefix argument:

routes = lambda: [
    controller('/products', ProductController),
]

Specify rules to only include those routes from the controller:

routes = lambda: [
    controller(SecurityController, rules=[
       # these inherit all unspecified kwargs from the decorated view methods
       rule('/login', SecurityController.login),  # methods=['GET', 'POST']
       rule('/logout', SecurityController.logout),  # methods=['GET']
       rule('/sign-up', SecurityController.register),  # methods=['GET', 'POST']
    ]),
]
Parameters
  • url_prefix_or_controller_cls – The controller class, or a url prefix for all of the rules from the controller class passed as the second argument

  • controller_cls – If a url prefix was given as the first argument, then the controller class must be passed as the second argument

  • rules – An optional list of rules to limit/customize the routes included from the controller

resource

flask_unchained.resource(url_prefix_or_resource_cls: Union[str, Type[flask_unchained.bundles.controller.resource.Resource]], resource_cls: Optional[Type[flask_unchained.bundles.controller.resource.Resource]] = None, *, member_param: Optional[str] = None, unique_member_param: Optional[str] = None, rules: Optional[Iterable[Union[flask_unchained.bundles.controller.route.Route, Iterable[flask_unchained.bundles.controller.route.Route]]]] = None, subresources: Optional[Iterable[Iterable[flask_unchained.bundles.controller.route.Route]]] = None) → Iterable[flask_unchained.bundles.controller.route.Route][source]

This function is used to register a Resource’s routes.

Example usage:

routes = lambda: [
    resource(ProductResource),
]

Or with the optional prefix argument:

routes = lambda: [
    resource('/products', ProductResource),
]

Specify rules to only include those routes from the resource:

routes = lambda: [
    resource('/users', UserResource, rules=[
       get('/', UserResource.list),
       get('/<int:id>', UserResource.get),
    ]),
]

Specify subresources to nest resource routes:

routes = lambda: [
    resource('/users', UserResource, subresources=[
       resource('/roles', RoleResource)
    ]),
]

Subresources can be nested as deeply as you want, however it’s not recommended to go more than two or three levels deep at the most, otherwise your URLs will become unwieldy.

Parameters
  • url_prefix_or_resource_cls – The resource class, or a url prefix for all of the rules from the resource class passed as the second argument.

  • resource_cls – If a url prefix was given as the first argument, then the resource class must be passed as the second argument.

  • member_param – Optionally override the controller’s member_param attribute.

  • rules – An optional list of rules to limit/customize the routes included from the resource.

  • subresources – An optional list of subresources.

func

flask_unchained.func(rule_or_view_func: Union[str, Callable], view_func: Optional[Callable] = <py_meta_utils._missing object>, blueprint: Optional[flask.blueprints.Blueprint] = <py_meta_utils._missing object>, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, methods: Union[List[str], Tuple[str], Set[str], None] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

This function allows to register legacy view functions as routes, eg:

@route('/')
def index():
    return render_template('site/index.html')

routes = lambda: [
    func(index),
]

It accepts an optional url rule argument:

routes = lambda: [
    func('/products', product_list_view),
]

As well as supporting the same kwargs as Werkzeug’s Rule, eg:

routes = lambda: [
    func('/', index, endpoint='home', methods=['GET', 'POST']),
]
Parameters
  • rule_or_view_func – The view function, or an optional url rule for the view function given as the second argument

  • view_func – The view function if passed a url rule as the first argument

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

include

flask_unchained.include(url_prefix_or_module_name: str, module_name: Optional[str] = None, *, attr: str = 'routes', exclude: Union[List[str], Tuple[str], Set[str], None] = None, only: Union[List[str], Tuple[str], Set[str], None] = None) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Include the routes from another module at that point in the tree. For example:

# project-root/bundles/primes/routes.py
routes = lambda: [
    controller('/two', TwoController),
    controller('/three', ThreeController),
    controller('/five', FiveController),
]


# project-root/bundles/blog/routes.py
routes = lambda: [
    func('/', index),
    controller('/authors', AuthorController),
    controller('/posts', PostController),
]


# project-root/your_app_bundle/routes.py
routes = lambda: [
    include('bundles.primes.routes'),

    # these last two are equivalent
    include('/blog', 'bundles.blog.routes'),
    prefix('/blog', [
        include('bundles.blog.routes'),
    ]),
]
Parameters
  • url_prefix_or_module_name – The module name, or a url prefix for all of the included routes in the module name passed as the second argument.

  • module_name – The module name of the routes to include if a url prefix was given as the first argument.

  • attr – The attribute name in the module, if different from routes.

  • exclude – An optional list of endpoints to exclude.

  • only – An optional list of endpoints to only include.

prefix

flask_unchained.prefix(url_prefix: str, children: Iterable[Union[flask_unchained.bundles.controller.route.Route, Iterable[flask_unchained.bundles.controller.route.Route]]]) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Sets a prefix on all of the child routes passed to it. It also supports nesting, eg:

routes = lambda: [
    prefix('/foobar', [
        controller('/one', OneController),
        controller('/two', TwoController),
        prefix('/baz', [
            controller('/three', ThreeController),
            controller('/four', FourController),
        ])
    ])
]
Parameters
  • url_prefix – The url prefix to set on the child routes

  • children

rule

flask_unchained.rule(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, methods: Union[List[str], Tuple[str], Set[str], None] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Used to specify customizations to the route settings of class-based view function. Unspecified kwargs will be inherited from the route decorated on each view. For example:

routes = lambda: [
    prefix('/api/v1', [
        controller(SecurityController, rules=[
           rule('/login', SecurityController.login,
                endpoint='security_api.login'),  # methods=['GET', 'POST']
           rule('/logout', SecurityController.logout,
                endpoint='security_api.logout'),  # methods=['GET']
           rule('/sign-up', SecurityController.register,
                endpoint='security_api.register'),  # methods=['GET', 'POST']
        ]),
    ],
]
Parameters
  • rule – The URL rule.

  • cls_method_name_or_view_fn – The view function.

  • defaults – Any default values for parameters in the URL rule.

  • endpoint – The endpoint name of this view. Determined automatically if left unspecified.

  • is_member – Whether or not this view is for a Resource member method.

  • methods – A list of HTTP methods supported by this view. Defaults to ['GET'].

  • only_if – A boolean or callable to dynamically determine whether or not to register this route with the app.

  • rule_options – Other kwargs passed on to Rule.

get

flask_unchained.get(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Like rule(), except specifically for HTTP GET requests.

Parameters
  • rule – The url rule for this route.

  • cls_method_name_or_view_fn – The view function for this route.

  • is_member – Whether or not this route is a member function.

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

patch

flask_unchained.patch(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Like rule(), except specifically for HTTP PATCH requests.

Parameters
  • rule – The url rule for this route.

  • cls_method_name_or_view_fn – The view function for this route.

  • is_member – Whether or not this route is a member function.

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

post

flask_unchained.post(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Like rule(), except specifically for HTTP POST requests.

Parameters
  • rule – The url rule for this route.

  • cls_method_name_or_view_fn – The view function for this route.

  • is_member – Whether or not this route is a member function.

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

put

flask_unchained.put(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Like rule(), except specifically for HTTP PUT requests.

Parameters
  • rule – The url rule for this route.

  • cls_method_name_or_view_fn – The view function for this route.

  • is_member – Whether or not this route is a member function.

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

delete

flask_unchained.delete(rule: str, cls_method_name_or_view_fn: Union[str, Callable, None] = None, *, defaults: Optional[Dict[str, Any]] = <py_meta_utils._missing object>, endpoint: Optional[str] = <py_meta_utils._missing object>, is_member: Optional[bool] = <py_meta_utils._missing object>, only_if: Union[bool, Callable[flask_unchained.flask_unchained.FlaskUnchained, bool], None] = <py_meta_utils._missing object>, **rule_options) → Iterable[flask_unchained.bundles.controller.route.Route][source]

Like rule(), except specifically for HTTP DELETE requests.

Parameters
  • rule – The url rule for this route.

  • cls_method_name_or_view_fn – The view function for this route.

  • is_member – Whether or not this route is a member function.

  • only_if – An optional function to decide at runtime whether or not to register the route with Flask. It gets passed the configured app as a single argument, and should return a boolean.

  • rule_options – Keyword arguments that ultimately end up getting passed on to Rule

Route

class flask_unchained.bundles.controller.route.Route(rule: Optional[str], view_func: Union[str, function], blueprint: Optional[flask.blueprints.Blueprint] = None, defaults: Optional[Dict[str, Any]] = None, endpoint: Optional[str] = None, is_member: bool = False, methods: Union[List[str], Tuple[str, ...], None] = None, only_if: Union[bool, function, None] = <py_meta_utils._missing object>, **rule_options)[source]

This is a semi-private class that you most likely shouldn’t use directly. Instead, you should use the public functions in Declarative Routing, and the route() and no_route() decorators.

This class is used to store an intermediate representation of route details as an attribute on view functions and class view methods. Most notably, this class’s rule and full_rule attributes may not represent the final url rule that gets registered with Flask.

Further gotchas with Controller and Resource routes include that their view_func must be finalized from the outside using TheControllerClass.method_as_view.

should_register(app: flask_unchained.flask_unchained.FlaskUnchained) → bool[source]

Determines whether or not this route should be registered with the app, based on only_if.

property defaults

The URL defaults for this route.

property endpoint

The endpoint for this route.

property is_member

Whether or not this route is for a resource member route.

property method_name

The string name of this route’s view function.

property methods

The HTTP methods supported by this route.

property module_name[source]

The module where this route’s view function was defined.

property rule

The (partial) url rule for this route.

property full_rule

The full url rule for this route, including any blueprint prefix.

property full_name

The full name of this route’s view function, including the module path and controller name, if any.

Hooks

RegisterBlueprintsHook

class flask_unchained.bundles.controller.hooks.RegisterBlueprintsHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers legacy Flask blueprints with the app.

name: str = 'blueprints'

The name of this hook.

bundle_module_names: Union[List[str], Tuple[str, ...], None] = ['views']

The default module this hook loads from.

Override by setting the blueprints_module_names attribute on your bundle class.

process_objects(app: flask_unchained.flask_unchained.FlaskUnchained, blueprints: List[flask.blueprints.Blueprint])[source]

Registers discovered blueprints with the app.

collect_from_bundles(bundles: List[flask_unchained.bundles.Bundle]) → List[flask.blueprints.Blueprint][source]

Find blueprints in bundles.

collect_from_bundle(bundle: flask_unchained.bundles.Bundle) → Iterable[flask.blueprints.Blueprint][source]

Finds blueprints in a bundle hierarchy.

type_check(obj)[source]

Returns True if obj is an instance of flask.Blueprint.

RegisterBundleBlueprintsHook

class flask_unchained.bundles.controller.hooks.RegisterBundleBlueprintsHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers a bundle blueprint for each bundle with views and/or template/static folders.

name: str = 'bundle_blueprints'

The name of this hook.

run_hook(app: flask_unchained.flask_unchained.FlaskUnchained, bundles: List[flask_unchained.bundles.Bundle], unchained_config: Optional[Dict[str, Any]] = None) → None[source]

Register blueprints for bundles, where necessary.

RegisterRoutesHook

class flask_unchained.bundles.controller.hooks.RegisterRoutesHook(unchained: flask_unchained.unchained.Unchained, bundle: Optional[flask_unchained.bundles.Bundle] = None)[source]

Registers routes.

name: str = 'routes'

The name of this hook.

bundle_module_name: Optional[str] = 'routes'

The default module this hook loads from.

Override by setting the routes_module_name attribute on your bundle class.

run_hook(app: flask_unchained.flask_unchained.FlaskUnchained, bundles: List[flask_unchained.bundles.Bundle], unchained_config: Optional[Dict[str, Any]] = None) → None[source]

Discover and register routes.

process_objects(app: flask_unchained.flask_unchained.FlaskUnchained, routes: Iterable[flask_unchained.bundles.controller.route.Route])[source]

Organize routes by where they came from, and then register them with the app.

get_explicit_routes(bundle: flask_unchained.bundles.Bundle)[source]

Collect routes from a bundle using declarative routing.

collect_from_bundle(bundle: flask_unchained.bundles.Bundle)[source]

Collect routes from a bundle when not using declarative routing.

type_check(obj)[source]

Returns True if obj was decorated with route() or if obj is a controller or resource with views.

FlaskForm

Using forms in Flask Unchained is exactly the same as it is with Flask-WTF.

class flask_unchained.FlaskForm(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)[source]

Base form class extending flask_wtf.FlaskForm. Adds support for specifying the field order via a field_order class attribute.

Parameters
  • formdata – Used to pass data coming from the end user, usually request.POST or equivalent. formdata should be some sort of request-data wrapper which can get multiple parameters from the form input, and values are unicode strings, e.g. a Werkzeug/Django/WebOb MultiDict

  • obj – If formdata is empty or not provided, this object is checked for attributes matching form field names, which will be used for field values.

  • prefix – If provided, all fields will have their name prefixed with the value.

  • data – Accept a dictionary of data. This is only used if formdata and obj are not present.

  • meta – If provided, this is a dictionary of values to override attributes on this form’s meta instance.

  • **kwargs – If formdata is empty or not provided and obj does not contain an attribute named the same as a field, form will assign the value of a matching keyword argument to the field, if one exists.

field_order = ()

An ordered list of field names. Fields not listed here will be rendered first.

Utility Functions

redirect

flask_unchained.redirect(where: Optional[str] = None, default: Optional[str] = None, override: Optional[str] = None, _anchor: Optional[str] = None, _cls: object = None, _external: Optional[bool] = False, _external_host: Optional[str] = None, _method: Optional[str] = None, _scheme: Optional[str] = None, **values) → flask.wrappers.Response[source]

An improved version of flask’s redirect function

Parameters
  • where – A URL, endpoint, or config key name to redirect to

  • default – A URL, endpoint, or config key name to redirect to if where is invalid

  • override – explicitly redirect to a URL, endpoint, or config key name (takes precedence over the next value in query strings or forms)

  • values – the variable arguments of the URL rule

  • _anchor – if provided this is added as anchor to the URL.

  • _cls – if specified, allows a method name to be passed to where, default, and/or override

  • _external – if set to True, an absolute URL is generated. Server address can be changed via SERVER_NAME configuration variable which defaults to localhost.

  • _external_host – if specified, the host of an external server to generate urls for (eg https://example.com or localhost:8888)

  • _method – if provided this explicitly specifies an HTTP method.

  • _scheme – a string specifying the desired URL scheme. The _external parameter must be set to True or a ValueError is raised. The default behavior uses the same scheme as the current request, or PREFERRED_URL_SCHEME from the app configuration if no request context is available. As of Werkzeug 0.10, this also can be set to an empty string to build protocol-relative URLs.

url_for

flask_unchained.url_for(endpoint_or_url_or_config_key: Optional[str], _anchor: Optional[str] = None, _cls: object = None, _external: Optional[bool] = False, _external_host: Optional[str] = None, _method: Optional[str] = None, _scheme: Optional[str] = None, **values) → Optional[str][source]

An improved version of flask’s url_for function

Parameters
  • endpoint_or_url_or_config_key – what to lookup. it can be an endpoint name, an app config key, or an already-formed url. if _cls is specified, it also accepts a method name.

  • values – the variable arguments of the URL rule

  • _anchor – if provided this is added as anchor to the URL.

  • _cls – if specified, can also pass a method name as the first argument

  • _external – if set to True, an absolute URL is generated. Server address can be changed via SERVER_NAME configuration variable which defaults to localhost.

  • _external_host – if specified, the host of an external server to generate urls for (eg https://example.com or localhost:8888)

  • _method – if provided this explicitly specifies an HTTP method.

  • _scheme – a string specifying the desired URL scheme. The _external parameter must be set to True or a ValueError is raised. The default behavior uses the same scheme as the current request, or PREFERRED_URL_SCHEME from the app configuration if no request context is available. As of Werkzeug 0.10, this also can be set to an empty string to build protocol-relative URLs.

abort

flask_unchained.abort(status, *args, **kwargs)[source]

Raises an HTTPException for the given status code or WSGI application.

If a status code is given, it will be looked up in the list of exceptions and will raise that exception. If passed a WSGI application, it will wrap it in a proxy WSGI exception and raise that:

abort(404)  # 404 Not Found
abort(Response('Hello World'))

generate_csrf

flask_unchained.generate_csrf(secret_key=None, token_key=None)[source]

Generate a CSRF token. The token is cached for a request, so multiple calls to this function will generate the same token.

During testing, it might be useful to access the signed token in g.csrf_token and the raw token in session['csrf_token'].

Parameters
  • secret_key – Used to securely sign the token. Default is WTF_CSRF_SECRET_KEY or SECRET_KEY.

  • token_key – Key where token is stored in session for comparision. Default is WTF_CSRF_FIELD_NAME or 'csrf_token'.