Django系列(3)-統一封裝Response消息體

親測,直接拷貝我代碼用就好,有問題請留言~

定義常見code

# 響應成功,狀態碼200
CODE_SUCCESS = '000000'
MSG_SUCCESS = '成功'
# token失效或權限認證錯誤,狀態碼401
CODE_AUTH_ERROR = '000001'
MSG_AUTH_ERROR = 'token認證失敗, 請重新登錄'
# 業務上的錯誤
CODE_BUSSINESS_ERROR = '000002'
MSG_BUSSINESS_ERROR = ''
# 服務器內部錯誤,狀態碼500
CODE_SERVER_ERROR = '000003'
MSG_SERVER_ERROR = '網絡操作失敗,請稍後重試'
# 未發現接口
CODE_NOT_FOUND_ERROR = '000004'
MSG_NOT_FOUND_ERROR = '服務器沒有此接口'
# 未知錯誤
CODE_UNKNOWN_ERROR = '000005'
MSG_UNKNOWN_ERROR = '未知錯誤'
# 拒絕訪問
CODE_REJECT_ERROR = '000006'
MSG_REJECT_ERROR = '拒絕訪問'
# 拒絕訪問
CODE_METHOD_ERROR = '000007'
MSG_METHOD_ERROR = '請求方法錯誤'
# 缺少參數
CODE_PARAMETER_ERROR = '000008'
MSG_PARAMETER_ERROR = '缺少參數'

自定義Response

from rest_framework.response import Response
from django.utils import six
from base.constant import CODE_SUCCESS, MSG_SUCCESS
from rest_framework import status

class BaseResponse(Response):
    def __init__(self, code=CODE_SUCCESS, message=MSG_SUCCESS, data={}, status=status.HTTP_200_OK,
                 template_name=None, headers=None, exception=False, content_type='application/json'):
        super(Response, self).__init__(None, status=status)
        self._code = code
        self._message = message
        self._data = data

        self.data = {"code": code, "message": message, "data": data}
        self.template_name = template_name
        self.exception = exception
        self.content_type = content_type

        if headers:
            for name, value in six.iteritems(headers):
                self[name] = value

    @property
    def code(self):
        return self._code

    @code.setter
    def code(self, value):
        self._code = value

    @property
    def message(self):
        return self._message

    @message.setter
    def message(self, value):
        self._message = value

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, value):
        self._data = value

自定義ModelViewSet基類

class BaseViewSet(ModelViewSet):
    pagination_class = CustomLimitOffsetPagination
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)

    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 BaseResponse(data=serializer.data, headers=headers)


    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 BaseResponse(data=serializer.data)

    def update(self, request, *args, **kwargs):
        """
        put /entity/{pk}/
        """
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return BaseResponse(data=serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        delete /entity/{pk}/
        """
        instance = self.get_object()
        self.perform_destroy(instance)
        return BaseResponse(message='數據刪除成功.')

自定義LimitOffsetPagination分頁類

class CustomLimitOffsetPagination(LimitOffsetPagination):
    limit = None

    def get_limit(self, request):
        if self.limit_query_param:
            try:
                value = request.query_params[self.limit_query_param]
                if int(value) == -1:
                    return int(value)
                else:
                    return _positive_int(
                        value,
                        strict=True,
                        cutoff=self.max_limit
                    )
            except (KeyError, ValueError):
                pass
        return self.default_limit

    def paginate_queryset(self, queryset, request, view=None):
        self.limit = self.get_limit(request)
        if self.limit == -1:
            return list(queryset)
        return super().paginate_queryset(queryset, request, view=None)

    def get_paginated_response(self, data):

        return BaseResponse(data={'count': self.count, 'results': data})

異常處理

from rest_framework.views import exception_handler
from base.constant import CODE_NOT_FOUND_ERROR, MSG_NOT_FOUND_ERROR, MSG_UNKNOWN_ERROR, CODE_UNKNOWN_ERROR, \
    CODE_AUTH_ERROR, MSG_AUTH_ERROR, CODE_SERVER_ERROR, MSG_SERVER_ERROR, MSG_REJECT_ERROR, CODE_REJECT_ERROR, \
    CODE_METHOD_ERROR, MSG_METHOD_ERROR, MSG_PARAMETER_ERROR, CODE_PARAMETER_ERROR


def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc, context)

    # Now add the HTTP status code to the response.
    if response is not None:
        response.data.clear()
        response.data['data'] = {}

        if response.status_code == 404:
            try:
                response.data['message'] = MSG_NOT_FOUND_ERROR
                response.data['code'] = CODE_NOT_FOUND_ERROR
            except KeyError:
                response.data['message'] = MSG_NOT_FOUND_ERROR

        if response.status_code == 400:
            response.data['message'] = MSG_PARAMETER_ERROR
            response.data['code'] = CODE_PARAMETER_ERROR

        elif response.status_code == 401:
            response.data['message'] = exc.detail
            response.data['code'] = CODE_AUTH_ERROR

        elif response.status_code >= 500:
            response.data['message'] = MSG_SERVER_ERROR
            response.data['code'] = CODE_SERVER_ERROR

        elif response.status_code == 403:
            response.data['message'] = MSG_REJECT_ERROR
            response.data['code'] = CODE_REJECT_ERROR

        elif response.status_code == 405:
            response.data['message'] = MSG_METHOD_ERROR
            response.data['code'] = CODE_METHOD_ERROR
    return response

setting.py中異常信息配置

REST_FRAMEWORK = {
    ......
    'EXCEPTION_HANDLER': (
        'your_app_path.custom_exception_handler'
    )
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章