Skip to content

Response Models

Each route handler has key-value pair of status codes and a response model. This response model holds information on the type of response to be returned.

# project_name/apps/items/controllers.py

from ellar.common import Controller, get, Serializer, ControllerBase

class UserSchema(Serializer):
    username: str
    email: str = None
    first_name: str = None
    last_name: str = None


@Controller
class ItemsController(ControllerBase):
    @get("/me", response=UserSchema)
    def me(self):
        return dict(username='Ellar', email='ellar@example.com')

During route response computation, the me route handler response will evaluate to a JSONResponseModel with UserSchema as content validation schema.

The resulting route responses will be:

from ellar.common import Serializer
from ellar.common.responses.models import JSONResponseModel


class UserSchema(Serializer):
    username: str
    email: str = None
    first_name: str = None
    last_name: str = None


response = {200: JSONResponseModel(model_field_or_schema=UserSchema)}

For documentation purposes, we can apply some description to the returned response

@get("/me", response=(UserSchema, 'User Schema Response'))
def me(self):
    return dict(username='Ellar', email='ellar@example.com')
This will be translated to:

response = {200: JSONResponseModel(model_field_or_schema=UserSchema, description='User Schema Response')}

response description

Info

Each route handler has its own ResponseModel computation and validation. If there is no response definition, Ellar default the route handler model to EmptyAPIResponseModel.

Override Response Type

When you use a Response class as response, a ResponseModel is used and the response_type is replaced with applied response class.

For example:

# project_name/apps/items/controllers.py

from ellar.common import Controller, get, ControllerBase,PlainTextResponse, Serializer


class UserSchema(Serializer):
    username: str
    email: str = None
    first_name: str = None
    last_name: str = None


@Controller
class ItemsController(ControllerBase):
    @get("/me", response={200: PlainTextResponse, 201: UserSchema})
    def me(self):
        return "some text response."
This will be translated to:

from ellar.common.responses.models import ResponseModel, JSONResponseModel
from ellar.common import PlainTextResponse

response = {200: ResponseModel(response_type=PlainTextResponse), 201: JSONResponseModel(model_field_or_schema=UserSchema)}

Response Model Properties

All response model follows IResponseModel contract.

import typing as t

from ellar.pydantic.fields import ModelField
from ellar.common import IExecutionContext, Response


class IResponseModel:
    media_type: str
    description: str
    get_model_field: t.Callable[..., t.Optional[t.Union[ModelField, t.Any]]]
    create_response: t.Callable[[IExecutionContext, t.Any], Response]
Properties Overview:

  • media_type: Read from response media type. Required
  • description: For documentation purpose. Default: Success Response. Optional
  • get_model_field: returns response schema if any. Optional
  • create_response: returns a response for the client. Optional

There is also a BaseResponseModel concrete class for more generic implementation. And its adds extra properties for configuration purposes.

They include:

  • response_type: Response classes eg. JSONResponse, PlainResponse, HTMLResponse. etc. Default: Response. Required
  • model_field_or_schema: Optional property. For return data validation. Default: None Optional

Different Response Models

Let's see different ResponseModel available in Ellar and how you can create one too.

ResponseModel

Response model that manages rendering of other response types.

  • Location: ellar.common.responses.models.ResponseModel
  • response_type: Response
  • model_field_or_schema: None
  • media_type: text/plain

JSONResponseModel

Response model that manages JSON response.

  • Location: ellar.common.responses.models.json.JSONResponseModel
  • response_type: JSONResponse OR config.DEFAULT_JSON_CLASS
  • model_field_or_schema: Required
  • media_type: application/json

HTMLResponseModel

Response model that manages HTML templating response. see @render decorator.

  • Location: ellar.common.responses.models.html.HTMLResponseModel
  • response_type: TemplateResponse
  • model_field_or_schema: None
  • media_type: text/html

FileResponseModel

Response model that manages FILE response. see @file decorator.

  • Location: ellar.common.responses.models.file.FileResponseModel
  • response_type: FileResponse
  • model_field_or_schema: ellar.common.responses.models.file.FileResponseModelSchema
  • media_type: Required

StreamingResponseModel

Response model that manages STREAMING response. see @file decorator.

  • Location: ellar.common.responses.models.file.StreamingResponseModel
  • response_type: StreamingResponse
  • model_field_or_schema: ellar.common.responses.models.file.StreamResponseModelSchema
  • media_type: Required

EmptyAPIResponseModel

Default ResponseModel applied when no response is defined.

  • Location: ellar.common.responses.models.json.EmptyAPIResponseModel
  • response_type: JSONResponse OR config.DEFAULT_JSON_CLASS
  • model_field_or_schema: dict
  • media_type: application/json

Custom Response Model

Lets create a new JSON response model.

# project_name/apps/items/controllers.py

import typing as t
from ellar.common import Controller, get, ControllerBase, JSONResponse, Serializer
from ellar.common.responses.models import ResponseModel


class NoteSchema(Serializer):
    id: t.Union[int, None]
    text: str
    completed: bool


class JsonApiResponse(JSONResponse):
    media_type = "application/vnd.api+json"


class JsonApiResponseModel(ResponseModel):
    response_type = JsonApiResponse
    model_field_or_schema = t.List[NoteSchema]
    default_description = 'Successful JsonAPI Response'


@Controller
class ItemsController(ControllerBase):
    @get("/notes/", response=JsonApiResponseModel())
    def get_notes(self):
        return [
            dict(id=1, text='My Json Api Response 1', completed=True),
            dict(id=2, text='My Json Api Response 2', completed=True),
        ]

JsonApiResponseModel Image