How to set a custom response body format globally?
See original GitHub issueHi, friends.I am using drf-spectacular==0.17.1
in a Django project(Django==3.2.4
& djangorestframework==3.12.4
) to generate API documentation. I have a question and want to ask for help
- I customized the ModelViewSet. Use a custom response body format(JsonResponse). As follows
from rest_framework import status
from rest_framework import viewsets
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from .custom_json_response import JsonResponse
class CustomModelViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_201_CREATED,
headers=headers)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return JsonResponse(data=[], msg='delete resource success', code=20000, status=status.HTTP_204_NO_CONTENT)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
class MyListRetrieveDestroyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
GenericViewSet):
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return JsonResponse(data=[], msg='delete resource success', code=20000, status=status.HTTP_204_NO_CONTENT)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
class MyListRetrieveModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return JsonResponse(data=serializer.data, msg='success', code=20000, status=status.HTTP_200_OK)
- The content of JsonResponse is as follows(see the
self.data = {'code': code, 'message': msg, 'data': data}
)
from rest_framework.response import Response
from rest_framework.serializers import Serializer
class JsonResponse(Response):
def __init__(self, data=None, code=None, msg=None,
status=None,
template_name=None, headers=None,
exception=False, content_type=None, **kwargs):
super().__init__(None, status=status)
if isinstance(data, Serializer):
msg = (
'You passed a Serializer instance as data, but '
'probably meant to pass serialized `.data` or '
'`.error`. representation.'
)
raise AssertionError(msg)
self.data = {'code': code, 'message': msg, 'data': data}
self.data.update(kwargs)
self.template_name = template_name
self.exception = exception
self.content_type = content_type
if headers:
for name, value in headers.items():
self[name] = value
- I extends the CustomModelViewSet class in views.py to achieve a unified response body format, as shown below
@extend_schema(tags=['项目管理'])
class ProjectsViewSet(CustomModelViewSet):
serializer_class = ProjectSerializer
permission_classes = [permissions.IsAuthenticated, IsObjectCreatorOrModifierInRequestUserGroups]
filterset_fields = ['project_name', 'project_desc', 'creator', 'modifier']
- The actual response body of the interface request is as follows:
{
"code": 20000,
"message": "success",
"data": {
"id": 1,
"create_time": "2021-06-14 13:54:26",
"update_time": "2021-06-14 13:54:26",
"creator": "anonymous",
"modifier": "anonymous",
"project_name": "测试项目1",
"project_desc": "测试项目description"
}
}
- But viewing the API document in the browser, the format of the response body is not displayed like
{"code": 20000, "message": "xxx", "data": "xxx"}
- So I want to ask, how to set the Schema of the unified response body format (
{"code": 20000, "message": "xxx", "data": "xxx"}
) globally? thank you very much.
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Format response data in ASP.NET Core Web API
ASP.NET Core MVC supports formatting response data, using specified formats or in response to a client's request.
Read more >Spring configure @ResponseBody JSON format
For the folks who are using Java based Spring configuration: @Configuration @ComponentScan(basePackages = "com.domain.sample") @EnableWebMvc public class ...
Read more >Customize HTTP Responses | Documentation
You can use a Global Request Filter to set Custom HTTP Headers and then short-circuit the request: public override void Configure(Container container) ...
Read more >Custom responses for Block actions - AWS Documentation
In the individual Block action settings, you reference the custom body that you want to use and you define the status code and...
Read more >Formatting Response Data - ASP.NET Core Documentation
You can use a tool like Fiddler to create a request that includes an Accept header and specify another format. In that case,...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
updated the FAQ (and the test) as this has come up a few times:
https://drf-spectacular.readthedocs.io/en/latest/faq.html#how-to-i-wrap-my-responses-my-endpoints-are-wrapped-in-a-generic-envelope
see issue #49