zoukankan      html  css  js  c++  java
  • 序列化组件+视图组件

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

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

  • 相关阅读:
    第04组 Beta冲刺 (2/5)
    第04组 Beta冲刺 (1/6)
    第04组 Alpha冲刺 总结
    二叉树的递归与非递归
    各类典例模板
    选择题合辑2
    运算符重载
    链表题目
    集合的模拟实现(类模板)
    2018Final静态成员(黑名单)
  • 原文地址:https://www.cnblogs.com/fengchong/p/10088659.html
Copyright © 2011-2022 走看看