-
Notifications
You must be signed in to change notification settings - Fork 0
Format results server side
To make the formatting of your result easier, you can define a generic object for your API class. It will be used automatically to format the results of your model. This object (called format_object
) contains the list of fields that you want to return. You could specify the model's field to use in a sub-object, with the key field
. If the key do not exist, the key of the sub-object is used as a field instead. Example:
from rest_api.API import API
from rest_api.errors import ResponseNotFound
from example.models import Project
class ProjectAPI(API):
format_object = {
"id": {},
"name": {},
"owner": {"field": "owner__email"}
}
# GET /api/1.0/project/<id>
def method_get_detail(self, session, request, _id, **kwargs):
try:
project = Project.objects.get(pk=_id)
except:
raise ResponseNotFound(details=["Project not found"])
return self.response(self.format(project))
$> curl -X GET http://127.0.0.1:8000/api/1.0/project/1
{
"id": 1,
"name": "Skies",
"owner": "[email protected]"
}
This method also works for the results of type list. Moreover, you can specify whether you don't want a specific field in this type (with the parameter list
to False
in the sub-object). It will be seen only with the type detail. Example:
from rest_api.API import API
from rest_api.errors import ResponseNotFound
from example.models import Project
class ProjectAPI(API):
format_object = {
"id": {},
"name": {},
"owner": {"field": "owner__email", "list": False}
}
# GET /api/1.0/project/<id>
def method_get_detail(self, session, request, _id, **kwargs):
try:
project = Project.objects.get(pk=_id)
except:
raise ResponseNotFound(details=["Project not found"])
return self.response(self.format(project))
$> curl -X GET http://127.0.0.1:8000/api/1.0/project
{
"count_results": 2,
"current_page": 1,
"format": {
"id": "id",
"name": "name"
},
"limit": 25,
"number_pages": 1,
"results": [
{
"id": 1,
"name": "Skies"
},
{
"id": 2,
"name": "ComeOn"
],
"total_results": 2
}
$> curl -X GET http://127.0.0.1:8000/api/1.0/project/1
{
"id": 1,
"name": "Skies",
"owner": "[email protected]"
}
The type list is automatically set when you call the method pagination
(LINK TO Pagination). If you don't call this method, you can force his type:
self.is_list = True
self.format(item)
By default, the method format
choice the format object self.format_object
. But you can specify an other format (for your custom route for example):
self.format(item, _format=self.format_object_contributors)
You could also find an example in project.py.
The sub-objects could be more complex. You can for example create really a sub-object in the result, in the key object
:
format_object = {
"id": {},
"name": {},
"owner": {
"object": {
"id": {"field": "owner__id"},
"email": {"field": "owner__email"}
}
}
}
$> curl -X GET http://127.0.0.1:8000/api/1.0/project/1
{
"id": 1,
"name": "Skies",
"owner": {
"id": 2,
"email": "[email protected]"
}
}
Or it may happen that one of the fields is a ManyToManyField
(an array of sub-results). In this case, you don't have to specify the field name in the key field
, but in the key object_list
:
format_object = {
"id": {},
"name": {},
"owner": {
"object": {
"id": {"field": "owner__id"},
"email": {"field": "owner__email"}
}
},
"contributors": {
"list": False,
"object_list": "contributors",
"object_list_order": "id",
"object": {
"id": {"field": "id"},
"email": {"field": "email"}
}
}
}
$> curl -X GET http://127.0.0.1:8000/api/1.0/project/2
{
"contributors": [
{
"email": "[email protected]",
"id": 2
},
{
"email": "[email protected]",
"id": 3
}
],
"id": 2,
"name": "ComeOn",
"owner": {
"email": "[email protected]",
"id": 1
}
}