序列化组件+视图组件

一、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

哈哈,是不是已经被惊呆了呢!

posted @ 2018-12-08 18:47  中杯可乐不加冰  阅读(177)  评论(0编辑  收藏  举报