序列化器類
一、Serializer序列化類
Serializer是DRF的序列化器基類,提供基本功能,使用Serializer類需要自己定義字段名稱和類型。
BookSerializer(Serializer):name = serializers.CharField()price = serlializers.IntegerField()date = serlializers.DateField()
Serializer序列化器類初始化的時候的幾個參數說明:
instance這個指從數據庫中讀取的記錄對應的對象,用于顯示或者編輯中的現有
many如果是true,則指傳遞了多個對象
data用于收集通過post傳上來的字典,用于新增或者編輯中的更新
Serializer序列化器提供了一個.save()接口用于保存數據,這個函數里面通過判斷instance是否有值來確定是新增還是更新,如果有值則調用self.update(),如果沒有值則調用self.create(),這兩個方法需要自己實現,以滿足用戶的新增或者修改的邏輯。
self.create(self, validated_data)
self.update(self, instance, validated_data)
實現了這兩個方法后,在客戶類里面需要新增或者保存的時候,只需統一的調用serializer.save()就可以了。
二、ModelSerializer類
使用ModelSerializer類,就不用再自己定義字段名稱和類型了,直接給出模型名稱,指出需要序列化的字段即可。
BookSerializer(ModelSerlizer):class Meta:model = Bookfields = [“name”, “date”] # 這里可以自己定義需要的字段,__all__表示所有字段,也可以自己定義字段名稱
使用ModelSerlializer類也不需要再自己定義create()和update()方法了,ModelSerlializer類已經實現了這兩個函數的定義。
視圖類
django里面的視圖實際上是業務邏輯存放的地方,也就是“功能”,并不是頁面樣式。
而業務的功能無非就是這5種:增、刪、改、查(列表)、查(詳情)
DRF里面提供了三大類的類:API、mixin、ViewSet,API類的類提供接口(get、post、put、update、delete),mixin提供功能,ViewSet負責包裝。
一、CBV視圖,基于類的視圖
django的原生視圖是基于函數的,也就是FBV。CBV是基于類的,繼承自View類。View類中有兩個重要的函數:
View.dispatch()
View.as_view()
在View.as_view()函數中,又定義了一個子函數view(),as_view()會返回這個函數。在基于函數(FBV)的視圖模式中,urls.py文件中指向的就是函數,而在基于類的視圖(CBV)中,urls.py文件中指向的是類的as_view()函數,注意這里是加了括號的,就是說是要直接執行這個函數的,而這個函數的執行結果,是里面的子函數vews()。子view()函數會調用View.dispatch()函數,用于通過反射,指向在客戶類中定義的get(),post(),put(),delete()等http方法的函數。
提示:CBV相對于FBV,改變了函數的組織形式,FBV是自己定義函數,通過路徑找到該函數。CBV是統一使用http的method,用過method名稱(get、post、put、update、delete),找到以該名稱定義的函數,實現增刪改查查。這也就是RESTFul。
二、APIView
APIView(View)類中也定義了以下兩個函數:
APIView.dispatch()
APIView.as_view()
其中,as_view()函數調用了csrf_exempt()函數用來處理跨域請求
使用APIView類也需要自己定義:get(),post(),put(),delete()等http方法函數。
相比django原生的CBV,這里的dispatch()函數包裝了request,提供了一個用于API的強大的request。另外還初始化了三個基礎功能:認證、權限、限流
提示:相對于基本CBV,APIView定制了request,專門用于API應用。另外還調用了三個基礎功能:認證、權限、限流。
三、通用視圖類GenericAPIView
通用視圖類GenericAPIView(APIView)
引入了兩個變量:
queryset表示數據集
serializer_class 表示序列化器類
get、post、put、delete等函數還需要有
提示:
1、這個類需要配合其他類,通過多繼承的方式使用。
2、有了數據集和序列化器類,我們還需要操作這些數據的方法:get、post、put…,下面的mixin系類分別定義了這些方法。以便根據自己的需求組合使用。
四、mixin混合類
mixins 是一種代碼復用機制,允許我們將多個組件共享的邏輯提取到一個獨立的對象中,從而提高代碼的可維護性和重用性。
這里新增了以下幾個類:CreateModelMixin、ListModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin,每一個類里面只實現了類名稱種的方法。注意這里的5個方法和增刪改查查中的5個方法名稱不一致,需要在定義一下增刪改查查方法,然后只需要在具體方法內返回對應的mixin方法即可。
例如,CreateModelMixin類實現了create方法,可以實現對數據庫的增加操作
ListModelMixin類實現了list方法,可以實現對數據庫的查詢操作
RetrieveModelMixin類實現了retrieve方法,可以實現對數據庫的查詢操作
UpdateModelMixin類實現了update方法,可以實現對數據庫的修改操作
DestroyModelMixin類實現了destroy方法,可以實現對數據庫的刪除操作
使用方法:在視圖類中繼承GenericAPIView類和以上幾個類,然后在視圖類中定義queryset和serializer_class屬性
最后在urls.py中配置路徑
例如:
urls.py
urlpatterns = [path('houseku/', HouseKuList.as_view()),
]
views.py
class HouseKuList(generics.ListCreateAPIView, generics.GenericAPIView):queryset = HouseKu.objects.all()serializer_class = HouseKuSerializer# 這里還要寫get、post、delete等函數,用于對應Mixin里面的list、create等def get(self, request):return self.list(request) def post(self, request):return self.create(request)
提示:GenericAPIView提供了queryset、serializer_class,mixin混合類提供了方法(但這些方法不對應的method名稱)這兩個組合在一起,就實現了相應的功能。
五、Mixin再封裝,優化后的APIView
Mixin里面實現了list、create等方法,但是并沒有對應http的method,DRF實現了進一步封裝,創造了以下類:
ListCreateAPIView、RetrieveUpdateDestroyAPIView、ListAPIView、CreateAPIView、RetrieveAPIView、UpdateAPIView、DestroyAPIView
注意這里面沒有mixin,而有API,通過繼承這些類,可以實現對應的http方法:get、post、put、delete等,到這里,我們的客戶類就不需要再寫get、post、put、delete等方法了
class HouseKuViewSet(generics.ListCreateAPIView, generics.GenericAPIView):queryset = HouseKu.objects.all()serializer_class = HouseKuSerializer
提示:這里,***APIView已經封裝了method對應名稱的方法,組合起來,再配合GenericAPIView,只要提供queryset和serializer_class,就實現了所有的功能。
六、ViewSet
到這里,就不用再寫兩個(BookView用戶列表,BookDetailView用于詳細)自定義的類了。可以合二為一,然后在urls.py里面as_view的參數里,把put、post、delete等method自定義的函數關聯起來就可以了。
ViewSet(ViewSetMixin, views.APIView)
ViewSetMixin里面的as_view()方法可以加參數,用于指定method方法到自定義方法的映射。
path(“book/”, views.BookView.as_view({“get”:”get_all”, “post”:”add_object”})
path(“book/(?P<pk>\d+)”,views.BookView.as_view({“get”:”get_object”, “delete”:”delete_object”, “put”:”update_object”})
七、示例
APIView
urls.py
urlpatterns = [path('user/', views.UserView.as_view()),path('user/<int:pk>/', views.UserDetailView.as_view()),
]
views.py
from rest_framework.views import APIViewclass UserView(APIView):def get(self, request):users = User.objects.all()serializer = UserSerializer(users, many=True)return Response(serializer.data)def post(self, request):serializer = UserSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status=201)return Response(serializer.errors, status=400)class UserDetailView(APIView):def get(self, request, pk):user = User.objects.get(pk=pk)serializer = UserSerializer(user)return Response(serializer.data)def put(self, request, pk):user = User.objects.get(pk=pk)serializer = UserSerializer(user, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=400)def delete(self, request, pk):user = User.objects.get(pk=pk)user.delete()return Response(status=204)
GenericAPIView
需配合一系列的Mixin來使用
urls.py
urlpatterns = [path('mixin/user/', views.UserMixinView.as_view()),path('mixin/user/<int:pk>/', views.UserMixinDetailView.as_view()),
]
views.py
class UserMixinView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):queryset = User.objects.all()serializer_class = UserSerializerdef get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, request, *args, **kwargs):return self.create(request, *args, **kwargs)class UserMixinDetailView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,generics.GenericAPIView):queryset = User.objects.all()serializer_class = UserSerializerdef get(self, request, *args, **kwargs):return self.retrieve(request, *args, **kwargs)def put(self, request, *args, **kwargs):return self.update(request, *args, **kwargs)def delete(self, request, *args, **kwargs):return self.destroy(request, *args, **kwargs)
ListCreateAPIView、RetrieveUpdateDestroyApiView
urls.py
urlpatterns = [path('generic/user/', views.UserGenericView.as_view()),path('generic/user/<int:pk>/', views.UserGenericDetailView.as_view()),
]
views.py
class UserGenericView(generics.ListCreateAPIView):queryset = User.objects.all()serializer_class = UserSerializerclass UserGenericDetailView(generics.RetrieveUpdateDestroyAPIView):queryset = User.objects.all()serializer_class = UserSerializer
ViewSet
urls.py
urlpatterns = [path('viewset/user/', views.UserViewSet.as_view({'get': 'list', 'post': 'create'})),path('viewset/user/<int:pk>/', views.UserViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
到這里,已經將兩個類合二為一了,最簡潔,但是也最不靈活,適合用于不添加任何自己邏輯的增刪改查查
views.py
class UserViewSet(viewsets.ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer