1. 程式人生 > 實用技巧 >DRF框架之APIView

DRF框架之APIView

在前面的文章中,我們後端序列化給前端都是以json資料返回,反序列化(post、put)也以json資料格式輸入,如果我們反序列化輸入的資料也想以application/x-www-form-urlencoded或者其它的格式輸入呢?又或者返回的資料想以html頁面的方式展示呢?

在django的檢視中,我們都知道需要繼承View這個類,在使用DRF框架後,我們的檢視可以來繼承APIView,它對django中的View做了一系列拓展,如:認證、授權、限流和不同請求資料的解析等等

一、引入方式

from rest_framework.views import APIView
from rest_framework.response import
Response from rest_framework import status

二、序列化Response<->Accept

1.Response

前面我們一般都使用的是JsonResponse來進行序列化輸出,使用了APIView之後,我們可以使用Response序列化輸出,它有以下特性:

  • 是對django中的HttpResponse進行了拓展
  • 實現了根據請求頭中的Accept引數來動態返回
  • 預設情況下,如果請求頭中不傳Accept引數,那麼通過頁面訪問會返回一個可瀏覽的API頁面(html),通過postman等工具呼叫會返回json格式資料
  • 如果Accept引數為text/html,那麼會返回可瀏覽的API頁面(html)
  • Response第一個引數為經過序列化之後的資料(序列化器類.data)
  • status指定響應狀態碼

部分程式碼展示:

from django.http import Http404
from django.db import connection
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Projects
from .serializers import
ProjectsModelSerializer class ProjectsPage(APIView): ''' 類檢視 ''' def get_object(self, pk): try: obj = Projects.objects.get(id__exact=pk) except Exception: raise Http404("引數錯誤") return obj def get(self, request, pk=None): if pk: obj = self.get_object(pk) serializer_obj = ProjectsModelSerializer(instance=obj) return Response({'code': 0, 'res': "success", 'msg': serializer_obj.data}, status=status.HTTP_200_OK) else: qs = Projects.objects.all() serializer_obj = ProjectsModelSerializer(instance=qs, many=True) return Response({'code': 0, 'res': "success", 'msg': serializer_obj.data}, status=status.HTTP_200_OK)

前端展示:

postman展示:

1.不指定Accept

1.指定Accept

2.渲染類

我們不指定Accept的使用,預設為返回json資料,但這又是為什麼呢?為什麼不會返回別的型別資料呢?在drf的全域性配置中,DEFAULTS屬性值有一個渲染類的配置

從該列表我們知道,不指定時為預設返回json,如果我們想返回除了JSONRenderer和BrowsableAPIRenderer之外的格式資料時,就需要將該列表在專案下的settings.py中的REST_FRAMEWORK屬性中進行重寫

三、反序列化Request<->Content-Type

1.Request

現在我們的需求不僅僅是隻使用json傳參,也需要支援x-www-form-urlencoded傳參,在django中,獲取json的引數使用的為request.body,獲取x-www-form-urlencoded引數使用的為request.POST,獲取查詢字串引數使用的為request.GET,那麼針對post這樣的請求,如果想同時支援json和x-www-form-urlencoded傳參,有沒有更好的方式呢?答案是有的,我們使用drf框架,檢視繼承APIView時,request就不是原來的HttpRequest物件了,而是drf中的Request物件了,我們打斷點看一下

當我們給post請求傳入json或者x-www-form-urlencoded時,獲取引數的方式都是request.data,查詢字串變成了request.query_params,因此我們可以輕輕鬆鬆地實現以上需求

針對Request,總結如下特性:

  • 繼承APIView之後,為drf中的Request類
  • 對django中的HttpRequest進行了拓展
  • 統一使用Request物件.data屬性獲取json格式資料、form表單引數和FILES,獲取的值為字典資料型別(QueryDict)
  • 查詢字串引數使用Request物件.query_params屬性獲取
from django.http import Http404
from django.db import connection
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Projects
from .serializers import ProjectsModelSerializer


class ProjectsPage(APIView):
    '''
    類檢視
    '''

    def post(self, request):

        serializer_check_obj = ProjectsModelSerializer(data=request.data)

        if not serializer_check_obj.is_valid():
            return Response({"code": 1, "res": "error", "msg": serializer_check_obj.errors},
                            status=status.HTTP_400_BAD_REQUEST)

        serializer_check_obj.save()

        return Response({'code': 0, 'res': "success", 'msg': serializer_check_obj.data},
                        status=status.HTTP_201_CREATED)

postman展示:

1.以json傳參

2.以表單傳參

2.解析類

同樣的,drf的配置中也有關於解析類的配置,如果需要拓展其它解析方式,依然可以重寫

四、踩坑記錄

1.丟擲問題:

2.問題解決:

如果遇到該類問題,報錯提示api.html不存在,則需要將專案下settings.py模組中TEMPLATES下的APP_DIRS設定為True即可解決