Django Rest Framework - 异常 ,返回值 ,分页

一. 异常
在使用Django Rest Framework的时候,如果发生异常的话,往往如下面所示:

{“detail”: “Not allowed.”}
1
但是后台往往想要的是常见的模式:

{
“desc”:“Not allowed.”,
“code”:400,
“data”:null
}

官网文档 还是很清楚的,我们需要自定义 异常处理,然后配置就可以了,比如:

  1. 实现

from rest_framework.views import exception_handler

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['code'] = response.status_code
    response.data['desc'] = response.data['detail']
    #response.data['data'] = None #可以存在
    del response.data['detail'] #删除detail字段

return response
  1. 配置

settings.py 中配置

REST_FRAMEWORK = {


‘EXCEPTION_HANDLER’: (
‘dataAPI.common.api_exception.custom_exception_handler’
)
#‘EXCEPTION_HANDLER’: ‘my_project.my_app.utils.custom_exception_handler’
}

二. 返回值
如异常所示,我们常常的返回值也是同样的类型 ,比如下面所示,基本数据格式和分页格式(后面说)

{
“desc”:“page success”, #描述信息
“code”:200, #响应码 以 2开头就是成功
“data”:{
“detail”:Array[2], #当前页数据列表
“total”:6, #页面总数
“page”:2 #当前页面
}
}

而我们使用Django Rest Framework 中 序列化的时候,直接就返回数据了,并不符合我们想要的数据,所以通过自定Response 进行数据返回 : 比如: 当然前提使用 APIView

from django.utils import six
from rest_framework.response import Response
from rest_framework.serializers import Serializer

class JsonResponse(Response):
“”"
An HttpResponse that allows its data to be rendered into
arbitrary media types.
“”"

def __init__(self, data=None, code=None, desc=None,
             status=None,
             template_name=None, headers=None,
             exception=False, content_type=None):
    """
    Alters the init arguments slightly.
    For example, drop 'template_name', and instead use 'data'.
    Setting 'renderer' and 'media_type' will typically be deferred,
    For example being set automatically by the `APIView`.
    """
    super(Response, self).__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, "desc": desc, "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

Example :

def get(self, request, house_pk):
house = get_object_or_404(House, pk=house_pk) #获取数据
data = HouseSerializer(house) #序列化
return api_response.JsonResponse(data=data.data, code=status.HTTP_200_OK, desc=‘get house success’) #使用上面的进行返回

结果:

success : 成功使用的是 JsonResponse 返回

{
“desc”: “get house success”,
“code”: 200,
“data”: {
“pk”: 7,
“name”: “VVVVVVV”,
“staff”: {
“phone”: “xxxxxxxxxx”,
“username”: “yuan”
}

fail : 失败使用的是上面异常进行处理 : custom_exception_handler

{
“code”: 404,
“desc”: “未找到。”
}

三.分页实现
如 结果返回值所示,很多使用都需要实现分页功能,然而 Django Rest Framework 自带的分页功能,只能在 mixins.ListModelMixin and generics.GenericAPIView classes 继承这两个类才可以使用,而我们通常为了灵活性,往往会继承APIView 来实现,那么我们就需要自已使用分页功能。

数据基本格式:

{
“desc”:“page success”, #描述信息
“code”:200, #响应码 以 2开头就是成功
“data”:{
“detail”:Array[2], #当前页数据列表
“total”:6, #页面总数
“page”:2 #当前页面
}
}

这里我就使用在api 接口上,比如我的 (自已可以添加其他验证,比如page_size 最大是多少):

from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from rest_framework import status

from dataAPI.common import api_response #第二条中的返回值格式 JsonResponse

def api_paging(objs, request, Serializer):
“”"
objs : 实体对象
request : 请求对象
Serializer : 对应实体对象的序列化
“”"
try:
page_size = int(request.GET.get(‘page_size’, 2))
page = int(request.GET.get(‘page’, 1))
except (TypeError, ValueError):
return api_response.JsonResponse(code=status.HTTP_400_BAD_REQUEST, desc=‘page and page_size must be integer!’)

paginator = Paginator(objs, page_size) # paginator对象
total = paginator.num_pages #总页数
try:
    objs = paginator.page(page)
except PageNotAnInteger:
    objs = paginator.page(1)
except EmptyPage:
    objs = paginator.page(paginator.num_pages)

serializer = Serializer(objs, many=True) #序列化操作

return api_response.JsonResponse(data={
    'detail': serializer.data,
    'page': page,
    'total': total
}, code=status.HTTP_200_OK, desc='page success') #返回

Example :

def get(self, request, format=None):
“”"
page_size : ?page=1&page_size=10
page :
“”"
farms = self.get_object_list() #获取数据
return api_paginator.api_paging(farms, request, FarmSerializer) #分页处理,并返回
结果:

{
“desc”: “page success”,
“code”: 200,
“data”: {
“detail”: [
{
“name”: “V3”,
},
{
“name”: “V2”,
}
],
“total”: 6, #总页数
“page”: 2 #当前页
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值