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')
response = {200: JSONResponseModel(model_field_or_schema=UserSchema, description='User Schema Response')}

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."
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]
- 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:- Optionalproperty. For return data validation. Default:- NoneOptional
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: JSONResponseORconfig.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: JSONResponseORconfig.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),
        ]
