Django Rest Framework-例外、戻り値処理とページング実装
一.異常
Django Rest Frameworkを使用する場合、異常が発生した場合は、次のようになります.
しかし、バックグラウンドでは一般的なパターンが求められます.
公式サイトのドキュメントはまだはっきりしています.例外処理をカスタマイズし、構成すればいいです.例えば、次のようにします.
1.実現
2.構成
settings.pyでの構成
二.戻り値
異常に示すように、通常の戻り値も同じタイプです.たとえば、以下に示すように、基本データフォーマットとページングフォーマット(後述)
Django Rest Frameworkでシーケンス化すると、直接データが返され、私たちが望んでいるデータに合わないので、カスタムResponseでデータが返されます.例えば、APIViewを前提にしています.
Example :
結果:
success:JsonResponseが正常に使用されました.
fail:失敗したのは上の異常で処理:custom_exception_handler
三.ページング実装
結果の戻り値に示すように、多くの使用にはページング機能が必要ですが、Django Rest Frameworkが持つページング機能は、
データの基本フォーマット:
ここではapiインタフェースを使用します.たとえば、page_sizeの最大数など、他の検証を追加できます.
Example :
結果:
完了
Django Rest Frameworkを使用する場合、異常が発生した場合は、次のようになります.
{"detail": "Not allowed."}
しかし、バックグラウンドでは一般的なパターンが求められます.
{
"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
2.構成
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
でこの2つのクラスを継承してこそ使用できますが、柔軟性のために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 #
}
}
完了