chapps.rest.routers.domains module

Domain record management implemented by factories

This module defines the various routes for manipulating Domain records. It also defines the JoinAssoc between Domain and User tables.

Normally, each API route would be a decorated function or coroutine definition. However, in this case, all the routes are created by factories from common. This makes it impossible to attach docstrings.

In order to provide basic documentation and some examples how to use those common API route coroutine factories, the routes will be described below, as part of the api docstring.

chapps.rest.routers.domains.api = <fastapi.routing.APIRouter object>

FastAPI APIRouter object for domains

I will include a few examples here, rather than copy in all of the code. It seems important to provide and annotate at least a few examples in order to ensure that others, or my later self, will understand how this is all intended to work.

First, a simple example: the listing route. Domain objects, like just about any object represented this way, need to be listable by API so that they can be viewed by a user before being modified, linked to other objects, queried, destroyed, etc. In chapps.rest.routers.common, coroutine factories are defined to create all of these API routes.

Listing Domains

Normally this would look like the route definitions in the live module, a decorated coroutine definition. Something like this:

@api.get("/", response_model=DomainsResp)
async def list_domains(
  item_id: int, qparams: dict = Depends(list_query_params)
):
    ... some code ...
    return DomainsResp.send(response, [...])

Instead, we invoke the decorator directly as a function. As a decorator-with-arguments, its return value is a closure which is the actual decorator. That real decorator expects our route function or coroutine as an argument. A factory from common is used to create that route coroutine.

Therefore, the actual route is created on the APIRouter like so:

api.get("/", response_model=DomainsResp)(
     list_items(Domain, response_model=DomainsResp)
)

Please note that the main data model class is provided. All of the routes in this module regard Domain as the main data model. Because this route is for listing objects/records, it uses a response type which includes a list.

What about a route which makes changes, especially one which is sensitive to the model’s associations to other models? Things become a little bit more complicated, but not by much.

Updating Domains

To update a Domain, we need to receive the data within a Domain object, plus optionally a list of User IDs, to associate with the Domain instead of whatever is currently associated with the Domain.

api.put("/", response_model=DomainResp)(
    update_item(Domain, response_model=DomainResp, assoc=domain_join_assoc)
)

In order to specify the associations to support in the route, a list of JoinAssoc objects may be provided to the assoc parameter.

(The following parameters and return type correspond to the APIRouter instance, which is callable. Sphinx autodoc makes it quite difficult to suppress this output.)

Parameters
Return type

None

chapps.rest.routers.domains.domain_join_assoc = [JoinAssoc(Domain, User, users, typing.List[int])]

Join association list for Domain objects