Serializers¶
The Serializer
class in the Ellar, is a custom class based on pydantic
models, which provides additional functionality specific to Ellar's requirements.
To use Serializer
in Ellar, you simply need to create a class that inherits from Serializer
and define your data model using pydantic fields. Here's an example of how you could define a serializer class for a user model:
from ellar.common import Serializer
class UserSerializer(Serializer):
name: str
email: str
age: int
With this setup, you can use the UserSerializer
class to validate incoming data and or serialize outgoing response data, ensuring that it matches the expected format before saving it to the database or returning it to the client.
Handling Responses¶
Let's see how we can use Serializer as a responses schema which will help us validate out data output and also provide documentation on route function response.
The response schema is defined on the HTTP method decorator.
For example:
# project_name/apps/items/controllers.py
from ellar.common import Controller, get, Serializer, ControllerBase
# Define a User class with username, email, first_name, and last_name attributes
class User:
def __init__(self, username: str, email:str=None, first_name:str=None, last_name:str=None) -> None:
self.username = username
self.email = email
self.first_name = first_name
self.last_name = last_name
self.is_authenticated = False
@property
def full_name(self) -> str:
assert self.first_name and self.last_name
return f'{self.first_name} {self.last_name}'
# Define a Serializer class to validate response data
class UserSchema(Serializer):
username: str
email: str = None
first_name: str = None
last_name: str = None
# Create a fake user object
current_user = User(username='ellar', email='ellar@example.com', first_name='ellar', last_name='asgi')
# Define an endpoint that returns the fake user's information
@Controller
class ItemsController(ControllerBase):
@get("/me", response=UserSchema)
def me(self):
return current_user
UserSerializer
class based on the Serializer
class. The User model represents a user with a username
, email
, first_name
, and last_name
. The UserSerializer
class is used to define the expected format of the response data in the /me
endpoint. When the /me
endpoint is called, it returns the current_user
object as the response. The UserSerializer
is then used to parse and validate the current_user
object, converting it into a dictionary representation that can be easily serialized to JSON. The resulting dictionary is then passed to the JSONResponseModel
for serialization to a JSON string and sending the response to the client.
Multiple Response Types¶
The response
parameter takes different shape. Let's see how to return a different response if the user is not authenticated.
# project_name/apps/items/controllers.py
from ellar.common import Controller, get, ControllerBase, Serializer
class User:
def __init__(self, username: str, email:str=None, first_name:str=None, last_name:str=None) -> None:
self.username = username
self.email = email
self.first_name = first_name
self.last_name = last_name
self.is_authenticated = False
@property
def full_name(self) -> str:
assert self.first_name and self.last_name
return f'{self.first_name} {self.last_name}'
class UserSchema(Serializer):
username: str
email: str = None
first_name: str = None
last_name: str = None
class MessageSchema(Serializer):
message: str
current_user = User(username='ellar', email='ellar@example.com', first_name='ellar', last_name='asgi')
@Controller
class ItemsController(ControllerBase):
@get("/me", response={200: UserSchema, 403: MessageSchema})
def me(self):
if not current_user.is_authenticated:
return 403, {"message": "Please sign in first"}
return current_user
@get("/login", response=MessageSchema)
def login(self):
if current_user.is_authenticated:
return dict(message=f'{current_user.full_name} already logged in.')
current_user.is_authenticated = True
return MessageSchema(
message=f'{current_user.full_name} logged in successfully.'
)
# the same as returning dict(message=f'{current_user.full_name} logged in successfully.')
Here, the response
parameter takes a KeyValuePair of the status
and response Schema
.
Info
Note that we returned a tuple of status code and response data (403, {"message": "Please sign in first"}
) to specify the response validation to use.
Using Response Type/Object As Response¶
You can use Response
type to change the format of data returned from endpoint functions.
# project_name/apps/items/controllers.py
from ellar.common import Controller, get, ControllerBase, PlainTextResponse
@Controller
class ItemsController(ControllerBase):
@get("/me", response=PlainTextResponse)
def me(self):
return "some text response."
Also, we can return response object from endpoint functions, and it will override initial response
declared before.
# project_name/apps/items/controllers.py
from ellar.common import Controller, get, Serializer, ControllerBase, PlainTextResponse
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 PlainTextResponse("some text response.", status_code=200)