二:视图使用进化
初识rest_framework,视图使用时,类继承APIview,每个类相似的冗余代码过多:
from rest_framework.views import APIView from rest_framework.response import Response from .models import * from django.shortcuts import HttpResponse from django.core import serializers from rest_framework import serializers class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__" #depth=1 class PublshSerializers(serializers.ModelSerializer): class Meta: model=Publish fields="__all__" depth=1 class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() bs=BookSerializers(book_list,many=True,context={'request': request}) return Response(bs.data) def post(self,request,*args,**kwargs): print(request.data) bs=BookSerializers(data=request.data,many=False) if bs.is_valid(): print(bs.validated_data) bs.save() return Response(bs.data) else: return HttpResponse(bs.errors) class BookDetailViewSet(APIView): def get(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj,context={'request': request}) return Response(bs.data) def put(self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj,data=request.data,context={'request': request}) if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors) class PublishViewSet(APIView): def get(self,request,*args,**kwargs): publish_list=Publish.objects.all() bs=PublshSerializers(publish_list,many=True,context={'request': request}) return Response(bs.data) def post(self,request,*args,**kwargs): bs=PublshSerializers(data=request.data,many=False) if bs.is_valid(): # print(bs.validated_data) bs.save() return Response(bs.data) else: return HttpResponse(bs.errors) class PublishDetailViewSet(APIView): def get(self,request,pk): publish_obj=Publish.objects.filter(pk=pk).first() bs=PublshSerializers(publish_obj,context={'request': request}) return Response(bs.data) def put(self,request,pk): publish_obj=Publish.objects.filter(pk=pk).first() bs=PublshSerializers(publish_obj,data=request.data,context={'request': request}) if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors)
path('book/', views.BookView.as_view()), re_path('^book/(\d+)', views.BookDetailView.as_view()),
rest_framework提供mixins类,让我们的代码变得简洁起来:
from rest_framework import serializers from app01 import models class BookSerializers(serializers.ModelSerializer): # authors = AuthorsSerializers(many=True) class Meta: model = models.Book # fields = ["title", "price", "publish_id", "pub_date", "authors"] fields = "__all__" extra_kwargs = { 'title': {"error_messages": {"required": "书名内容不能为空"}}, 'publish': {"error_messages": {"required": '出版社不能为空'}}, 'price': {"error_messages": {"required": '价格不能为空'}} } # depth = 1 # 获取表中的多对多字段深度 class AuthorSerializers(serializers.ModelSerializer): class Meta: model = models.Author # fields = ["title", "price", "publish_id", "pub_date", "authors"] fields = "__all__" class PublishSerializers(serializers.ModelSerializer): class Meta: model = models.Publish # fields = ["title", "price", "publish_id", "pub_date", "authors"] fields = "__all__"
from rest_framework import mixins from rest_framework import generics class AuthorView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = models.Author.objects.all() serializer_class = serializers.AuthorSerializers def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class AuthorDetailView(mixins.DestroyModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, generics.GenericAPIView): queryset = models.Author.objects.all() serializer_class = serializers.AuthorSerializers def 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)
path('author/', views.AuthorView.as_view()), re_path('^author/(?P<pk>\d+)', views.AuthorDetailView.as_view()),
通过使用mixins类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py
模块。
class PublishView(generics.ListCreateAPIView): queryset = models.Publish.objects.all() serializer_class = serializers.PublishSerializers class PublishDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = models.Publish.objects.all() serializer_class = serializers.PublishSerializers
path('publish/', views.PublishView.as_view()), re_path('^publish/(?P<pk>\d+)', views.PublishDetailView.as_view())
现在使用起来已经非常简洁了,但依然需要将get、post与put、delete分开写成两个类,怎么才能在一个类下就完成这些操作呢,viewsets.ModelViewSet利用url很好的解决了这个问题。
from rest_framework import viewsets class BookView(viewsets.ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializers.BookSerializers
path('book/', views.BookView.as_view({'get': 'list', 'post': 'create'})), re_path('^book/(\d+)', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),