• 序列化组件的使用及接口设计和优化


    首先我们要知道常用的请求格式

      - GET       127.0.0.1:8080/books/           # 获取所有数据, 返回值 [ { }, { } ]

      - GET       127.0.0.1:8080/books/{ id }    # 获取一条数据源,返回值  { }

      - POST     127.0.0.1:8080/books/           # 新增一条数据, 返回值 : { }

      - PUT        127.0.0.1:8080/books/{ id }     # 修改数据,返回值 { }

      - DELETE 127.0.0.1:8080/books/{ id }     #  删除数据,返回空

    序列化

    表结构

    from django.db import models
    
    # Create your models here.
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        def __str__(self):
            return self.name
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        # 外键字段
        publish = models.ForeignKey(to="Publish", related_name="book", related_query_name="book_query", on_delete=models.CASCADE)
        # 多对多字段
        authors = models.ManyToManyField(to="Author")
    model.py

    一  

    - get接口设计  - 导入模块

    from rest_framework import serializers

      - 建立一个序列化类

    class BookSerializer(serializers.Serializer):
        字段自定义

      - 获取queryset

    origin_data = Book.objects.all()

      - 开始序列化

    serialized_data - BookSerializer(origin_data , many= True)

      - 获取序列化后的数据,返回给客户端

    return Response(serialized_data.data)

    注意:

      - 外键字段,显示__str__方法的返回值

      - 多对多字段需要自己动手获取数据

        通过serializerMethodField() 方法

    1 authors_list = serializers.SerializerMethodField()
    2 
    3     def get_authors_list(self, book_obj): # 注意 该方法 必须get_+上述字段名
    4         author_list = list()
    5 
    6         for author in book_obj.authors.all():
    7             author_list.append(author.name)
    8 
    9         return author_list

    附上代码

     - 视图

    1 class BookView(APIView):
    2     def get(self, request):
    3         origin_data = Book.objects.all()
    4 
    5         serialized_data = BookSerializer(origin_data, many=True)
    6 
    7         return Response(serialized_data.data)
    View Code

     - app_serializers.py

    class BookSerializer(serializers.Serializer):
        # nid = serializers.CharField(max_length=32)
        title = serializers.CharField(max_length=128)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        publish = 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')
        # authors = serializers.CharField(max_length=32) # book_obj.authors.all()
    
        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
    View Code

     - post接口设计

       视图

    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class BookView(APIView):
        def get(self, request):
            origin_data = Book.objects.all()
            
            serialized_data = BookSerializer(origin_data, many=True)
            
            return Reponse(serialized_data.data)
            
        def post(self, request):
            verified_data = BookSerializer(data=request.data)
            
            if verified_data.is_valid():
                book = verified_data.save()
                authors = Author.objects.filter(nid__in=request.data['authors'])
                book.authors.add(*authors)
                return Response(verified_data.data)
            else:
                return Response(verified_data.errors)
    View Code

        app_serializers.py

    class BookSerializer(serializers.Serializer):
        # nid = serializers.CharField(max_length=32)
        title = serializers.CharField(max_length=128)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        publish = 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')
        # authors = serializers.CharField(max_length=32) # book_obj.authors.all()
    
        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):
            # {'title': 'Python666', 'price': Decimal('66.00'), 'publish': '2'}
            validated_data['publish_id'] = validated_data.pop('publish')
            book = Book.objects.create(**validated_data)
    
            return book
    View Code

      - get取一条数据接口,put接口, delete接口:

    app_serializers.py不变

    class BookFilterView(APIView):
        def get(self, request, nid):
            book_obj = Book.object.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, many=False)
            if verified_data.is_valid():
                verified_data.save()
                return Response(verified_data.data)
            else:
                return Response(verified_data.errors)
                
        def delete(self, request, nid):
            book_obj = Book.objects.get(pk=nid).delete()
    View Code

    你有没有发现如果使用serializers.Serializer会有如下问题:

      - 需要手动插入数据(必须自定义create)

      - 手动序列化需要的字段

    实际上我们并不会用上述的这几种逻辑方式,因为drf已经帮我们封装好了

    使用视图组件的mixin进行接口逻辑优化

    让我们引入他们

    from rest_framework.mixins import (
         ListModelMixin
         CreateModelMixin
         DestroyModelMixin      
         UpdateModelMixin
         RetrieveModelMinxin
    )
    from rest_framework.generics import GenericAPIView

     - app_serializers.py

    from rest_framework import serializers
    
    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')    # 通过source 指定具体字段  , read_only也是只读
        publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city')
    
        author_list = serializers.SerializerMethodField()  # 多对多
    
        def get_author_list(self, book_obj):
            # 拿到queryset开始循环 [{}, {}, {}, {}]
            authors = list()
    
            for author in book_obj.authors.all():
                authors.append(author.name)
    
            return authors
    View Code

     - 视图

    class BookView(ListModelView, CreateModelView, GenericAPIView):
        queryset = Book.objcets.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):
            return retrieve(request, *args, **kwargs)
            
        def put(self, request, *args, **kwargs):
            return update(request, *args, **kwargs)
            
        def delete(self, request, *args, **kwargs)
            return destroy(request, *args, **kwargs)
    View Code

    注意:单条数据操作的url是这样的:re_path(r'books/(?P<pk>d+)/$, views.BookFilterView.as_view())

     三

    第二点中的逻辑还可以进一步优化

    通过视图组件的view进行接口优化
     - 导入模块

    from rest_framework import generics

     - app_serializers.py同二

     - 视图

    class BookView(generics.ListCreateAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        
    class BookFilterView(generics.RetrieveUpdateDestoryAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer

    是不是觉得通过view进行优化已达极致,其实不然还有viewset,让我们一起来玩一玩

    首先要想用viewset,我们就得重新设计urls

     - urls

    from django.urls import re_path
    from serializer 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'
        }))
    ]
    View Code

    - app_serializers.py不变

     - 视图

    from rest_framework.viewsets import ModelViewSet
    
    class BookView(ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
  • 相关阅读:
    openresty 使用 log_by_lua 发送日志到 syslog-ng
    uuid 了解
    基于openresty 的几个开发框架
    openresty 几个插件使用
    kong 了解
    openresty && hashids&& redis 生成短链接
    kong k8s 安装 以及可视化管理界面
    hashids 了解
    Apache Tez 了解
    Cascalog了解
  • 原文地址:https://www.cnblogs.com/lzmdbk/p/10079594.html
Copyright © 2020-2023  润新知