請求與響應、檢視
阿新 • • 發佈:2020-07-21
目錄
請求與響應、檢視
請求
#請求物件,把原來的request重新封裝 from rest_framework.request import Request def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): # 二次封裝request,將原生request作為drf request物件的 _request 屬性 self._request = request #.取值的時候從self._request(request)去獲取對應的資料 def __getattr__(self,item): return getattr(self._request,item) #前端三種編碼格式傳入的資料,都可以從請求物件.data取 #請求物件.query_params與Django中的request.GET相同,只是換了個合適的名稱
響應
#from rest_framework.response import Response def __init__(self, data=None, status=None, template_name=None, headers=None, exception=False, content_type=None): #data 你要返回的資料(是字典) #status 返回的狀態碼,預設200(ok) from rest_framework import status路徑,把所有的狀態碼定義成了常量,這樣使用status.常量名 return Response({'status':status.HTTP_208_ALREADY_REPORTED}) #headers 響應頭,是字典可以放值,Response.headers['key']=values #content_type 響應的編碼格式,postman響應成application/json,瀏覽器是text/html #template_name 渲染的模板名字(自定製模板),不需要了解 #drf預設的配置檔案查詢順序 專案的settings.py>>>rest_framework.settings #drf的配置資訊,先從自己類>>>專案的setting.py>>>rest_framework.settings
檢視
#兩個檢視基類 APIView GenericAPIView #基於APIView寫介面 from rest_framework.views import APIView from app01.models import Book from app01.ser import BookSerializer from rest_framework import status class BookAPIView(APIView): def get(self,request,*args,**kwargs): #沒有pk,查所有 if not kwargs.get('pk'): book_list = Book.objects.all() book_ser = BookSerializer(book_list,many=True)#many序列化多條 return Response(book_ser.data) else: #查單個 book = Book.objects.filter(pk=kwargs.get('pk')).first() book_ser = BookSerializer(book) return Response(book_ser.data) #新增一個 def post(self,request): book_ser = BookSerializer(data=request.data) if book_ser.is_valid(): book_ser.save()#基於Serializer的需要在序列化類寫create方法 return Response(book_ser.data) else: return Response({'status':101,'msg':'校檢失敗'}) def put(self,request,*args,**kwargs): book = Book.objects.filter(pk=kwargs.get('pk')).first() #修改需要傳入修改的物件,修改的資料,序列化類寫update方法 book_ser = BookSerializer(instance=book,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校檢失敗'}) def delete(self,request,*args,**kwargs): book = Book.objects.filter(pk=kwargs.get('pk')).delete() return Response({'status':100,'msg':'刪除成功'}) #序列化類是Serializer,需要在序列化類寫create、update方法,ModelSerializer不用 def create(self, validated_data): book_obj = Book.objects.create(**validated_data) return book_obj def update(self, instance, validated_data): instance.name = validated_data.get('name') instance.price = validated_data.get('price') instance.author = validated_data.get('author') instance.save() return instance #路由配置 #BookAPIView re_path('bookapiview/(?P<pk>\d+)',views.BookAPIView.as_view()), path('bookapiview/',views.BookAPIView.as_view()), #基於GenericAPIView寫介面 from rest_framework.generics import GenericAPIView class BookGenericAPIView(GenericAPIView): queryset = Book.objects.all() serializer_class = BookModelSerializer def get(self,*args,**kwargs): if kwargs.get('pk'): book = Book.objects.filter(pk=kwargs.get('pk')).first() book_ser = self.get_serializer(book) return Response(book_ser.data) else: book_list = self.get_queryset() book_ser = self.get_serializer(book_list,many=True) return Response(book_ser.data) def post(self,request): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校檢失敗'}) def put(self,request,*args,**kwargs): book = Book.objects.filter(pk=kwargs.get('pk')).first() book_ser = self.get_serializer(instance=book, data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校檢失敗'}) def delete(self,*args,**kwargs): Book.objects.filter(pk=kwargs.get('pk')).delete() return Response({'status':100,'msg':'刪除成功'}) #路由配置 # BookGenericAPIView re_path('bookgeneric/(?P<pk>\d+)', views.BookGenericAPIView.as_view()), path('bookgeneric/', views.BookGenericAPIView.as_view()), #基於GenericAPIView和5個檢視擴充套件類寫介面 from rest_framework.generics import GenericAPIView from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin class BookGenerricmixin(GenericAPIView,ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin): queryset = Book.objects.all() serializer_class = BookModelSerializer def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: return self.retrieve(request,pk) else: return self.list(request) def post(self,request): return self.create(request) def put(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: return self.update(request,pk) else: return Response({'status':101,'msg':'沒有pk值'}) def delete(self,request,*args,**kwargs): pk=kwargs.get('pk') if pk: return self.destroy(request,pk) else: return Response({'status':101,'msg':'沒有pk值'}) #路由配置 # Bookgenerricmixin path('bookgenerricmixin/', views.BookGenerricmixin.as_view()), re_path('bookgenerricmixin/(?P<pk>\d+)', views.BookGenerricmixin.as_view()),
使用ModelViewSet編寫的5個介面手寫路由
#每個請求方式對應的方法
path('books5/', views.BookModelViewSet.as_view(actions={'get':'list','post':'create'}))
re_path('books5/(?P<pk>\d+)', views.BookModelViewSet.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'}))
原始碼分析ViewMixin
# 重寫了as_view
# 核心程式碼(所以路由中只要配置了對應關係,比如{'get':'list'}),當get請求來,就會執行list方法
for method, action in actions.items():
#method:get
# action:list
handler = getattr(self, action)
#執行完上一句,handler就變成了list的記憶體地址
setattr(self, method, handler)
#執行完上一句 物件.get=list
#for迴圈執行完畢 物件.get:對著list 物件.post:對著create
繼承ViewSetMixin的檢視類
# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前
def get_all_book(self,request):
print("xxxx")
book_list = Book.objects.all()
book_ser = BookSerializer(book_list, many=True)
return Response(book_ser.data)
# urls.py
#繼承ViewSetMixin的檢視類,路由可以改寫成這樣
path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),