1. 程式人生 > 實用技巧 >請求與響應、檢視

請求與響應、檢視

目錄

請求與響應、檢視

請求

#請求物件,把原來的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'})),

檢視繼承關係