使用django-rest-framework可以非常方便的基于django实现Restful API,但通常各个公司都会有各自的Restful API接口规范,可能会与框架默认的不太一样,这时候就需要能定制一下响应的格式。
借助于django的类继承机制,django-rest-framework提供了非常灵活的方式来实现,代码如下:
# coding: utf-8
from rest_framework import exceptions
from rest_framework import status, viewsets
from rest_framework.response import Response
class CustomModelViewSet(viewsets.ModelViewSet):
def handle_exception(self, exc):
"""
Handle any exception that occurs, by returning an appropriate response,
or re-raising the error.
"""
if isinstance(exc, (exceptions.NotAuthenticated,
exceptions.AuthenticationFailed)):
# WWW-Authenticate header for 401 responses, else coerce to 403
auth_header = self.get_authenticate_header(self.request)
if auth_header:
exc.auth_header = auth_header
else:
exc.status_code = status.HTTP_403_FORBIDDEN
exception_handler = self.settings.EXCEPTION_HANDLER
context = self.get_exception_handler_context()
response = exception_handler(exc, context)
if response is None:
self.raise_uncaught_exception(exc)
response.exception = True
response.data = {
'msg': response.data.values()[0][0],
'code': response.status_code,
'data': {}
}
response.status_code = status.HTTP_200_OK
return response
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 Response(
{
"msg": "create success",
"code": 200,
"data": {
"detail": serializer.data
}
},
status=status.HTTP_201_CREATED,
headers=headers
)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(
{
"msg": "retrieve success",
"code": 200,
"data": {
"detail": serializer.data
}
}
)
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
# refresh the instance from the database.
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(
{
"msg": "update success",
"code": 200,
"data": {
"detail": serializer.data
}
}
)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
data = serializer.data
self.perform_destroy(instance)
return Response(
{
"msg": "destroy success",
"code": 200,
"data": {
"detail": data
}
}
)