ModelSerializer序列化器实战

博客 分享
0 143
张三
张三 2022-03-31 22:57:25
悬赏:0 积分 收藏

ModelSerializer序列化器实战

ModelSerializer序列化器实战 使用ModelSerializer序列化器如何写接口?这里源码demo都写全了~一看就懂!

目录
  • ModelSerializer序列化器实战
  • 单表操作
    • 序列化器类
    • 视图类
    • 路由
    • 模型
  • 多表操作
    • models.py
    • serializer.py
    • views.py
    • urls.py

ModelSerializer序列化器实战

经历了源码的痛苦,掌握DRF的核心序列化器

上篇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 APIViewfrom .models import Bookfrom rest_framework.response import Responsefrom app01.serializer import  BookSerializer1class 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 modelsclass 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 tablesclass 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 lclass 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 modelsfrom 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 Responsefrom rest_framework.views import APIViewfrom app01 import modelsfrom 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 adminfrom django.urls import pathfrom app01 import viewsurlpatterns = [    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()),]

image

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

posted @ 2022-03-31 20:47 HammerZe 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员