Skip to content

Anatomy of Controllers

Tip

Make sure you've already read the Essentials Guide about controllers before getting started with this page

As described earlier in Essentials Guide to define controller you have to:

  • Use the framework-specific decorator @Controller() above the Python class of the controller.
  • The controller class should contain methods wrapped by HTTP Method-specific decorators to define route endpoints
  • It is recommended to use type annotations over HTTP endpoints for data validation. Each return value of a method is also processed by the framework.
1
2
3
4
5
@Controller(
    standalone=True,
)
class HttpController:
    ...

You can also specify controller-specific metadata (especially if you're using automatic router graph generation).

Metadata such as prefix, name, suffix, and other parameters passed to the @Controller decorator are collectively referred to as the controller's metadata

@Controller(
    prefix="some-prefix",
    name="http",
    suffix="some-suffix",
    standalone=True
) # will generate URL: /some-prefix/http/some-suffix/...
class HttpController:
    ...

Automatic router graph generation allows you to generate router graph's routes automatically based on your controllers' metadata, for more information please read Router Graph Guide.

Using Controllers

To use your controller, you should have it to be loaded in Ascender Framework as an HTTP router. So each controller that should be loaded, should be tied to specific router node, you can create manually router node in routes.py or generate the router node based on your controller's metadata.

Manually defining Router Node

To manually define router node in router graph, you have to define list with dictionaries in it that describes each route for router graph, usually there's already routes.py file which should be automatically generated by Ascender Framework CLI. But you can define your own.

from typing import Sequence
from ascender.core.router.interface.route import RouterRoute

from controllers.http.http_controller import HttpController


routes: Sequence[RouterRoute] = [
    {
        "path": "/some-prefix/http/some-suffix", # We define it manually here
        "controller": HttpController,
        "include_in_schema": True # Adds this controller and path into OpenAPI documentation schema (e.g. displaying in Swagger or ReDoc)
    }
]

__all__ = ["routes"]

Automatically generating Router Node from Controllers

Ascender Framework allows you to generate router graph and uses it under the hood. Only what you need is an AscModule to gather them all in one place.

controllers_module.py
@AscModule(
    imports=[
        MainController,
        HttpController
    ],
    declarations=[],
    providers=[],
    exports=[
        MainController, # Pass all controllers to `exports` of module
        HttpController
    ]
)
class ControllersModule: ...

Then pass this ControllersModule as provider to your application module if application is standalone application or to appBootstrap as provider as well if your application is not standalone

app_module.py
from ascender.core.router import provideRouterFromControllers
from controllers.controllers_module import ControllersModule

@AscModule(
    imports=[],
    declarations=[],
    providers=[
        provideRouterFromControllers(ControllersModule),
    ],
    exports=[]
)
class AppModule: ...

This loads all controllers exported in ControllersModule, it also uses metadata of controllers to build desired http route