一、Django自带的serializer
from django.shortcuts import render, HttpResponse from django.core.serializers import serialize from rest_framework.views import APIView from .models import Course class CourseView(APIView): def get(self, request): origin_data = Course.objects.all() # 开始序列化 serialized_data = serialize("json", origin_data) return HttpResponse(serialized_data)
二、DRF序列化组件
serializers.py #创建一个序列化类 from rest_framework import serializers from .models import Book class BookSerializer(serializers.Serializer): title = serializers.CharField(max_length=128) price = serializers.DecimalField(max_digits=5, decimal_places=2) publish_id = serializers.CharField() publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name') publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city') # 多对多字段需要自己手动获取数据,SerializerMethodField() authors_list = serializers.SerializerMethodField() #注意,多对多字段默认为只读字段,只读字段的名称可以不必和数据库的名称相对应,序列化类不对只读字段进行校验 def get_authors_list(self, book_obj): author_list = list() for author in book_obj.authors.all(): author_list.append(author.name) return author_list def create(self, validated_data): book = Book.objects.create(**validated_data) return book def update(self, instance, validated_data): pass # 备注:如果继承serializers.Serializer类,必须重新自定义create方法和update方法
urls.py from app01 import views urlpatterns = [ re_path(r'books/$', views.BookView.as_view()), re_path(r'books/(?P<nid>d+)/$', views.BookFilterView.as_view()), ]
views.py #增删改查接口设计 from rest_framework.views import APIView from rest_framework.response import Response from .models import ( Book, Publish, Author, ) from .app_serializers import BookSerializer class BookView(APIView): def get(self, request): # 获取queryset origin_data = Book.objects.all() # 开始序列化 serialized_data = BookSerializer(origin_data, many=True) return Response(serialized_data.data) def post(self, request): verified_data = BookSerializer(data=request.data) if verified_data.is_valid(): book = verified_data.save() #执行BookSerializer序列化类里自定义的create方法 authors = Author.objects.filter(nid__in=request.data['authors']) book.authors.add(*authors) return Response(verified_data.data) else: return Response(verified_data.errors) class BookFilterView(APIView): def get(self, request,nid): book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(book_obj, many=False) return Response(serialized_data.data) def put(self, request, nid): book_obj = Book.objects.get(pk=nid) verified_data = BookSerializer(data=request.data, instance=book_obj) #有instance为更新操作,反之为新增操作 if verified_data.is_valid(): verified_data.save() #执行BookSerializer序列化类里自定义的update方法 return Response(verified_data.data) else: return Response(verified_data.errors) def delete(self, request, nid): book_obj = Book.objects.get(pk=nid).delete() return Response()
总结:DRF的序列化组件代码相信你已经看出来了,序列化类的字段、create、update的方法都需要我们自己自定义,并且视图类的每个接口的代码都需要我们自己完成,这就相当的麻烦了,相信你一定不满足于这样麻烦冗余的代码吧,所以为了解决这样的问题,DRF为我们封装了视图组件,哈哈,功能十分强大哦!
三、DRF视图组件
功能:视图组件是用来优化接口逻辑的
(一)使用视图组件的mixin进行接口逻辑优化
首先我们仍然需要自定义一个序列化类,如果你不在想自己写create和update方法,那么我们的自定义序列化类需要继承serializers.ModelSerializer,其内部已经帮我们封装好所需的方法啦!
serializers.py from rest_framework import serializers from .models import Book class BookSerializer(serializers.ModelSerializer): class Meta: model = Book fields = ('title', 'price', 'publish', 'authors', 'author_list', 'publish_name', 'publish_city' ) extra_kwargs = { 'publish': {'write_only': True}, 'authors': {'write_only': True} } publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name') publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city') author_list = serializers.SerializerMethodField() def get_author_list(self, book_obj): authors = list() for author in book_obj.authors.all(): authors.append(author.name) return authors #备注:如果继承serializers.ModelSerializer,不需要自定义create和update方法,ModelSerializer类已经封装好了这些方法
urls.py from django.urls import re_path from app01 import views urlpatterns = [ re_path(r'books/$', views.BookView.as_view()), re_path(r'books/(?P<pk>d+)/$', views.BookFilterView.as_view()), ]
views.py from rest_framework.response import Response from rest_framework.mixins import ( ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin ) from rest_framework.generics import GenericAPIView from .models import ( Book, Publish, Author, ) from .app_serializers import BookSerializer class BookView(ListModelMixin, CreateModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookSerializer 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 BookFilterView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookSerializer def get(self, request, *args, **kwargs): # print(self.kwargs) {'pk': '1'} return self.retrieve(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs)
有没有发现我们的接口代码优化了不少呢?但你可能发现仍然会出现代码重复的现象,而且引入的类写起来十分的长,如果你的增删改查逻辑里没有太多自定义的功能的话,往下看下去,我们有更简洁的方法哦!
(二)generics.ListCreateAPIView、generics.RetrieveUpdateDestroyAPIView
这套组件不需要我们在自己写增删改查的接口逻辑啦,只需要你像DRF提供queryset和serializer_class就可以啦!
serializers.py和urls.py我们不做改变,下面我们只重新写views.py
from rest_framework import generics from .models import ( Book, Publish, Author, ) from .app_serializers import BookSerializer class BookView(generics.ListCreateAPIView): #查看所有和增加一条数据接口代码 queryset = Book.objects.all() serializer_class = BookSerializer class BookFilterView(generics.RetrieveUpdateDestroyAPIView): #获取单条数据、修改一条数据、删除一条数据接口 queryset = Book.objects.all() serializer_class = BookSerializer
(三)接口逻辑终结者------------ModelViewSet
这里我们仍然沿用上面的序列化类,但是需要重写urls.py和views.py
urls.py from django.urls import re_path from app01 import views urlpatterns = [ re_path(r'books/$', views.BookView.as_view({ 'get': 'list', 'post': 'create' })), re_path(r'books/(?P<pk>d+)/$', views.BookView.as_view({ 'get': 'retrieve', 'put': 'update', 'delete': 'destroy' })) ]
views.py from rest_framework.viewsets import ModelViewSet from .models import ( Book, Publish, Author, ) from .app_serializers import BookSerializer class BookView(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer
哈哈,是不是已经被惊呆了呢!