1. 程式人生 > 程式設計 >django rest framework 自定義返回方式

django rest framework 自定義返回方式

大家在用Django Rest Framework的時候會發現預設繼承後,增刪改查的返回資訊都是一段data,這是因為我實際是狀態碼和資訊你在呼叫api的時候是看不到的,僅僅如此麼?並不是這樣,在我前端呼叫後端的時候,實際上相關的code和msg是能看得到的,但是我們在普通的呼叫api他只是單單的返回data資訊,這個是不夠我們滿足需求的,畢竟我們不僅僅需要用前端需呼叫,下面我們來自定義Response返回資訊

Django(2.0)

Django Rest Framework

Python3.6

1、自定義Response,繼承rest framework的Response

#這個方法py檔案我們可以寫到任意地方,目的是在我們需要寫一個Baseview的時候將放回方法引用

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,msg=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,"message": msg,"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

2、重寫Base類,將增刪改查方法重寫並且返回方法為剛剛定義好的新的Response類

#Base類,將增刪改查方法重寫
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from assets import serializers
from assets import models
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.pagination import PageNumberPagination
from django.shortcuts import get_object_or_404
from common.utils.custom_response import JsonResponse
from rest_framework import filters
from django_filters import rest_framework
from django_filters.rest_framework import DjangoFilterBackend

class CustomViewBase(viewsets.ModelViewSet):
 # pagination_class = LargeResultsSetPagination
 # filter_class = ServerFilter
 queryset = ''
 serializer_class = ''
 permission_classes = ()
 filter_fields = ()
 search_fields = ()
 filter_backends = (rest_framework.DjangoFilterBackend,filters.SearchFilter,filters.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 JsonResponse(data=serializer.data,msg="success",code=201,status=status.HTTP_201_CREATED,headers=headers)

 def list(self,**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,code=200,status=status.HTTP_200_OK)

 def retrieve(self,**kwargs):
  instance = self.get_object()
  serializer = self.get_serializer(instance)
  return JsonResponse(data=serializer.data,status=status.HTTP_200_OK)

 def update(self,**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,status=status.HTTP_200_OK)

 def destroy(self,**kwargs):
  instance = self.get_object()
  self.perform_destroy(instance)
  return JsonResponse(data=[],code=204,msg="delete resource success",status=status.HTTP_204_NO_CONTENT)

3、view檢視繼承以及測試

class BatchLoadView(CustomViewBase):
 queryset = models.Manufacturer.objects.all()
 serializer_class = serializers.ManufacturerSerializer

 def list(self,**kwargs):
  return JsonResponse(code=200,data=[],msg="testings")

這樣我們就完成了自定義返回資訊,下一節將講解自定義異常

補充知識:django rest framework 自定義異常返回

上一節給大家介紹了自定義Response返回資訊,但那個只用於正確的返回success,但是當我們用到了許可權

auth 401、方法不允許method 405,等等,這時候我們就用自己自定義異常返回資訊

1、定義settings配置檔案

#定義異常返回的路徑指令碼位置

REST_FRAMEWORK = {
  'EXCEPTION_HANDLER': 'common.utils.custom_execption.custom_exception_handler',}

2、定義指令碼

#注意,指令碼路徑需要與settings.py 定義的一樣

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:
    print(response.data)
    response.data.clear()
    response.data['code'] = response.status_code
    response.data['data'] = []

    if response.status_code == 404:
      try:
        response.data['message'] = response.data.pop('detail')
        response.data['message'] = "Not found"
      except KeyError:
        response.data['message'] = "Not found"

    if response.status_code == 400:
      response.data['message'] = 'Input error'

    elif response.status_code == 401:
      response.data['message'] = "Auth failed"

    elif response.status_code >= 500:
      response.data['message'] = "Internal service errors"

    elif response.status_code == 403:
      response.data['message'] = "Access denied"

    elif response.status_code == 405:
      response.data['message'] = 'Request method error'
  return response

#無需呼叫,報錯的時候他自己會呼叫!!

以上這篇django rest framework 自定義返回方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。