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. Requireddescription
: For documentation purpose. Default:Success Response
. Optionalget_model_field
: returns response schema if any. Optionalcreate_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
. Requiredmodel_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
ORconfig.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
ORconfig.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),
]