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

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

  - 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

 

posted @ 2018-12-07 16:38  阵浊秀  阅读(336)  评论(0编辑  收藏  举报