DRF框架之APIView


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

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

  • 繼承Django中的View
  • APIView與View的不同之處
    • 傳入到視圖方法中的是Request對象,而不是Django的HttpRequest對象
    • 視圖方法可以返回Response對象,會為響應數據處理(render)為符合前端要求的格式
    • 任何APIException異常都會被捕獲到,並且處理成合適的響應信息
    • 在進行dispatch()分發前,會對請求進行身份認證、權限檢查、流量控制
  • 常用類屬性
    • authentication_classes列表或元組,身份認證類
    • permission_classes列表或元組,權限檢查類
    • throttle_classes列表或元組,流量控制類

一、引入方式

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,則會采用默認方式處理響應數據(默認返回json格式的數據)
  • 可以指定響應默認渲染類
  • Response(data, status=None, template_name=None, headers=None, content_type=None)
  • 參數說明
    • data
      • 序列化處理后的數據
      • 一般為serializer.data(python基本數據類型:字典、嵌套字典的列表)
    • status
      • 狀態碼,默認為200
    • template_name
      • 模板名稱,使用HTNLRenderer渲染時需指明
    • headers
      • 用於存放響應頭信息的字典
    • content_type
      • 響應頭中的Content-Type
      • 通常此參數無需設置,會自動根據前端所需類型數據來設置該參數

 

部分代碼展示:

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,總結如下特性:

  • 對Django中的HttpRequest進行了拓展
    • 會根據請求頭中的Content-Type,自動進行解析
    • 無論前端發送的哪種格式的數據,都可以以相同的方式讀取
  • request.data
    • 類似於Django中的request.POST和request.FILES
    • 可以對POST、PUT、PATCH的請求體參數進行解析
    • 不僅支持form傳參,也支持json格式傳參
  • request.query_params
    • 類似於Django中的request.GET
    • 獲取查詢字符串參數
  • 支持Django HttpRequest中所有的對象和方法

 

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即可解決


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM