ModelSerializer序列化器实战

ModelSerializer序列化器实战

上篇ModelSerializer序列化器做了一个小demo,演示了如何操作单表进行序列化和反序列化来实现五个API的使用,多表大差不差????,这里对四个表写五个API接口

单表操作

单表操作序列化类demo:

序列化器类

# ModelSerializer和表模型有绑定关系 class BookSerializer1(serializers.ModelSerializer):     class Meta:         model = Book  # 指定和哪个表有关系         # 所有字段         # fields = '__all__'         # 这里注意id字段是从表模型映射过来的,auto自增的,不传也可以         # 自定制的字段不传必须注册,在列表中         fields = ['id', 'title', 'price', 'price_info']  # 指定字段         extra_kwargs = {             'title': {'write_only': True, 'max_length': 8, 'min_length': 3}         }     # 指定序列化的字段:两种写法:在序列化类中写;models中写     price_info = serializers.SerializerMethodField()     def get_price_info(self, obj):         return "价格是:" + str(obj.price)     '''     注意:自定制字段如果和表模型获取到的字段是同名,那么自定制返回给前端的字段值就被自定制覆盖了,比如:     title = serializers.SerializerMethodField()     def get_title(self, obj):         return "书名是:" + str(obj.title)     '''      #  局部和全局钩子,跟之前一样,但是要注意写在Meta外

视图类

from rest_framework.views import APIView from .models import Book from rest_framework.response import Response from app01.serializer import  BookSerializer1 class BookView1(APIView):     def get(self, request):         # 从数据库查数据,做序列化         book_list = Book.objects.all()         # 实例化类,传入初始化的参数,instance和many         '''         instance:要序列化的对象  qs,单个对象         many:如果是qs对象,many=True,如果是单个对象many=False         '''         ser = BookSerializer1(instance=book_list, many=True)         # ser.data使用模型类的对象得到序列化后的字典         return Response(ser.data)      def post(self,request):         # 反序列化,保存到数据库使用data参数         deser = BookSerializer1(data=request.data)         # 校验数据         if deser.is_valid():             # 保存需要重写create方法,不然不知道存到哪个表             deser.save()             return Response(deser.data)         return Response({'code':101,'msg':'校验不通过','errors':deser.errors})    # 处理修改再写一个视图类,防止get冲突 class BookDetailView1(APIView):     def get(self,request,pk):         book = Book.objects.filter(pk=pk).first()         ser = BookSerializer1(instance=book)  # 这里设置了主键值,单条记录many不需要写         return Response(ser.data)     def delete(self,request,pk):         res = Book.objects.filter(pk=pk).delete()         print(res) # (1, {'app01.Book': 1})         # res是影响的行数         if res[0]>0:             return Response({'code': 100, 'msg': '删除成功'})         else:             return  Response({'code': 103, 'msg': '要删除的数据不存在'})      # 反序列化修改     def put(self,request,pk):         # 修改处理单条数据用过pk确定求改哪条数据         book = Book.objects.filter(pk=pk).first()         # 序列化器类实例化需要传入instance,data才表示修改         ser = BookSerializer1(instance=book,data=request.data)         if ser.is_valid():             # 重写update方法才能存入             ser.save()             return Response(ser.data)         return Response({'code':101,'msg':'校验未通过','error':ser.errors})

路由

path('books1/', views.BookView1.as_view()), path('books1/<int:pk>', views.BookDetailView1.as_view()),

模型

from django.db import models class Book(models.Model):     title = models.CharField(max_length=32)     price = models.DecimalField(max_digits=5,decimal_places=2)     authors = models.CharField(max_length=32)

多表操作

models.py

from django.db import models    # build four model tables  class Book(models.Model):     name = models.CharField(max_length=32)     price = models.DecimalField(decimal_places=2, max_digits=5)     publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)     authors = models.ManyToManyField(to='Author')      def __str__(self):         return self.name      # 自定制字段     @property     def publish_detail(self):         return {'name': self.publish.name, 'addr': self.publish.city}      @property     def author_list(self):         l = []         print(self.authors.all()) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>         for author in self.authors.all():             print(author.author_detail) # AuthorDetail object (1)             l.append({'name': author.name, 'age': author.age, 'addr': author.author_detail.addr})         return l   class Author(models.Model):     name = models.CharField(max_length=32)     age = models.IntegerField()     author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)      def __str__(self):         return self.name      @property     def authordetail_info(self):         return {'phone':self.author_detail.telephone,'addr':self.author_detail.addr}   class AuthorDetail(models.Model):     telephone = models.BigIntegerField()     addr = models.CharField(max_length=64)   class Publish(models.Model):     name = models.CharField(max_length=32)     city = models.CharField(max_length=32)     email = models.EmailField()

serializer.py

from app01 import models from rest_framework import serializers   # 书序列化器 class BookSerializer(serializers.ModelSerializer):     class Meta:         # 指定和哪个表有关系         model = models.Book         # fields = '__all__'         fields = ['id','name','price','publish','authors','publish_detail','author_list']         # 将关联表的信息全部取出来,不推荐使用         # depth = 1          extra_kwargs = {             'publish':{'write_only':True},             'authors':{'write_only':True}         }  # 作者序列化器 class AuthorSerializer(serializers.ModelSerializer):     class Meta:         # 指定和哪个表有关系         model = models.Author         # fields = '__all__'         fields = ['id', 'name', 'age', 'author_detail', 'authordetail_info']         extra_kwargs = {             'author_detail': {'write_only': True},         }   # 作者详情序列化器 class AuthorDetailSerializer(serializers.ModelSerializer):     class Meta:         # 指定和哪个表有关系         model = models.AuthorDetail         fields = '__all__'  # 出版社序列化器 class PublishSerializer(serializers.ModelSerializer):     class Meta:         # 指定和哪个表有关系         model = models.Publish         fields = '__all__'

views.py

from rest_framework.response import Response from rest_framework.views import APIView  from app01 import models from app01 import serializer   # 书视图类 class BookView(APIView):     def get(self, requets):         # 序列化         book_list = models.Book.objects.all()         # 序列化多条数据many=True         ser = serializer.BookSerializer(instance=book_list, many=True)         return Response(ser.data)      def post(self, request):         # 获取反序列化数据         ser = serializer.BookSerializer(data=request.data)         if ser.is_valid():             # 校验通过存入数据库,不需要重写create方法了             ser.save()             return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})         # 校验失败         return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors})   class BookViewDetail(APIView):     def get(self, request, pk):         book = models.Book.objects.filter(pk=pk).first()         ser = serializer.BookSerializer(instance=book)         return Response(ser.data)      def put(self, request, pk):         book = models.Book.objects.filter(pk=pk).first()         # 修改,instance和data都要传         ser = serializer.BookSerializer(instance=book, data=request.data)         if ser.is_valid():             # 校验通过修改,不需要重写update             ser.save()             return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})         # 校验不通过         return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors})      def delete(self, request, pk):         models.Book.objects.filter(pk=pk).delete()         return Response({'code': 100, 'msg': '删除成功'})   # 作者视图类 class AuthorView(APIView):     def get(self, requets):         # 序列化         author_list = models.Author.objects.all()         # 序列化多条数据many=True         ser = serializer.AuthorSerializer(instance=author_list, many=True)         return Response(ser.data)      def post(self, request):         # 获取反序列化数据         ser = serializer.AuthorSerializer(data=request.data)         if ser.is_valid():             # 校验通过存入数据库,不需要重写create方法了             ser.save()             return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})         # 校验失败         return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors})   class AuthorViewDetail(APIView):     def get(self, request, pk):         book = models.Author.objects.filter(pk=pk).first()         ser = serializer.AuthorSerializer(instance=book)         return Response(ser.data)      def put(self, request, pk):         book = models.Author.objects.filter(pk=pk).first()         # 修改,instance和data都要传         ser = serializer.AuthorSerializer(instance=book, data=request.data)         if ser.is_valid():             # 校验通过修改,不需要重写update             ser.save()             return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})         # 校验不通过         return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors})      def delete(self, request, pk):         models.Author.objects.filter(pk=pk).delete()         return Response({'code': 100, 'msg': '删除成功'})   # 作者详情视图类 class AuthorDetailView(APIView):     def get(self, requets):         # 序列化         author_list = models.AuthorDetail.objects.all()         # 序列化多条数据many=True         ser = serializer.AuthorDetailSerializer(instance=author_list, many=True)         return Response(ser.data)      def post(self, request):         # 获取反序列化数据         ser = serializer.AuthorDetailSerializer(data=request.data)         if ser.is_valid():             # 校验通过存入数据库,不需要重写create方法了             ser.save()             return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})         # 校验失败         return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors})   class OneAuthorViewDetail(APIView):     def get(self, request, pk):         book = models.AuthorDetail.objects.filter(pk=pk).first()         ser = serializer.AuthorDetailSerializer(instance=book)         return Response(ser.data)      def put(self, request, pk):         book = models.AuthorDetail.objects.filter(pk=pk).first()         # 修改,instance和data都要传         ser = serializer.AuthorDetailSerializer(instance=book, data=request.data)         if ser.is_valid():             # 校验通过修改,不需要重写update             ser.save()             return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})         # 校验不通过         return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors})      def delete(self, request, pk):         models.AuthorDetail.objects.filter(pk=pk).delete()         return Response({'code': 100, 'msg': '删除成功'})  # 出版社视图类 class PublishView(APIView):     def get(self, requets):         # 序列化         author_list = models.Publish.objects.all()         # 序列化多条数据many=True         ser = serializer.PublishSerializer(instance=author_list, many=True)         return Response(ser.data)      def post(self, request):         # 获取反序列化数据         ser = serializer.PublishSerializer(data=request.data)         if ser.is_valid():             # 校验通过存入数据库,不需要重写create方法了             ser.save()             return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})         # 校验失败         return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors})   class PublishViewDetail(APIView):     def get(self, request, pk):         book = models.Publish.objects.filter(pk=pk).first()         ser = serializer.PublishSerializer(instance=book)         return Response(ser.data)      def put(self, request, pk):         book = models.Publish.objects.filter(pk=pk).first()         # 修改,instance和data都要传         ser = serializer.PublishSerializer(instance=book, data=request.data)         if ser.is_valid():             # 校验通过修改,不需要重写update             ser.save()             return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})         # 校验不通过         return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors})      def delete(self, request, pk):         models.Publish.objects.filter(pk=pk).delete()         return Response({'code': 100, 'msg': '删除成功'})

urls.py

from django.contrib import admin from django.urls import path  from app01 import views  urlpatterns = [     path('admin/', admin.site.urls),     # 书     path('books/', views.BookView.as_view()),     path('books/<int:pk>', views.BookViewDetail.as_view()),      # 作者     path('authors/', views.AuthorView.as_view()),     path('authors/<int:pk>', views.AuthorViewDetail.as_view()),      # 作者详情     path('authorsdetail/', views.AuthorDetailView.as_view()),     path('authorsdetail/<int:pk>', views.OneAuthorViewDetail.as_view()),      # 出版社     path('publish/', views.PublishView.as_view()),     path('publishdetail/<int:pk>', views.PublishViewDetail.as_view()), ]

ModelSerializer序列化器实战

优化操作

我们知道作者表和作者详情表的表关系是一对一的关系,那么新增数据的时候,就得先新增作者详情表,再增作者表的数据,但是在实际生活中,用户不知道表关系这码事,为了体验更好,可以重写create方法,同时存两个表的内容,给用户的感觉就是操作了一张表

'''优化作者表的序列化器''' # 作者序列化器 class AuthorSerializer(serializers.ModelSerializer):     class Meta:         # 指定和哪个表有关系         model = models.Author         # fields = '__all__'         fields = ['id', 'name', 'age', 'telephone', 'addr','authordetail_info']      # 重写字段telephone和addr     telephone = serializers.CharField(write_only=True)     addr = serializers.CharField(write_only=True,max_length=8,required=False)       # 重写create,操作两个表     def create(self, validated_data):         # 先存作者详情         authordetail = models.AuthorDetail.objects.create(telephone=validated_data.get('telephone'),addr=validated_data.get('addr'))         # 存作者表         author = models.Author.objects.create(author_detail=authordetail,name=validated_data.get('name'),age=validated_data.get('age'))         # 这样只返回author对象就行,直接存了两个表,返回反序列化的对象         return author

ModelSerializer序列化器实战
ModelSerializer序列化器实战

Postman自行测试,我测了测都能用,有问题望指正~

注意
如果实际项目中不需要操作数据库可以使用APIView,如果操作数据库那么推荐使用GenericAPIView