在前面的文章中,我們后端序列化給前端都是以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
- 通常此參數無需設置,會自動根據前端所需類型數據來設置該參數
- data
部分代碼展示:
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即可解決