首页 > 其他分享 >序列化的高级用法与ModelSerializer的使用

序列化的高级用法与ModelSerializer的使用

时间:2023-05-18 19:44:45浏览次数:51  
标签:ModelSerializer ser author detail publish 用法 序列化 data

序列化的高级用法与ModelSerializer的使用

序列化高级用法之source(了解)

source的三个用法:
    1. 取别名:
    	book_name = serializers.CharField(source='name')  # book_name为前端可以看到的字段值,name是对象真实的属性。注意:别名和真实属性不能相同
    2. 美化值:
    	# 写在序列化类中
    	book_name = serializers.CharField(source='sb_name')  # 此时指定的就是方法名
        # 写在表模型中
        def sb_name(self):
        	return self.name + '_sb'
	3. 关联查询:
    	publish_name = serializers.CharField(source='publish.name')  # 必须有关联关系

序列化高级用法之定制字段的两种方式(非常重要)

# 方式一:在序列化类中写
    1 写一个字段,对应的字段类是:SerializerMethodField
    2 必须对应一个get_字段名的方法,方法必须接受一个obj,返回什么,这个字段对应的value就是什么
    
# 方式二:在表模型中写
    1 在表模型中写一个方法(可以使用:property),方法有返回值(字典,字符串,列表)
    2 在序列化类中,使用DictField,CharField,ListField

序列化类中写

### 定制字段方式1
class BookSerialzier(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    # 拿出出版社的id和名字和addr,放到一个字典中
    # 方式一:SerializerMethodField来定制,如果写了这个,必须配合一个方法get_字段名,这个方法返回什么,这个字段的值就是什么
    publish_detail = serializers.SerializerMethodField()

    def get_publish_detail(self, book):
        # print(obj) # 要序列化的book对象
        return {'id': book.publish.pk, 'name': book.publish.name, 'addr': book.publish.addr}

    # 练习:拿出所有作者的信息--》多条 [{name:,phone:},{}]
    author_list = serializers.SerializerMethodField()

    def get_author_list(self, book):
        l = []
        for author in book.authors.all():
            l.append({'id': author.pk, 'name': author.name, 'phone': author.phone, 'age': author.author_detail.age})
        return l

表模型中写

# 定制字段方式2
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
        extra_kwargs = {
            'title': {'max_length': 8},
            'publish': {'write_only': True},
            'author': {'write_only': True},
        }
    # 写在序列化类中
    # 在序列化中叫什么在表模型中也要交什么
    publish_detail = serializers.DictField(read_only=True) 
    author_list = serializers.ListField(read_only=True)

# 写在表模型中

    @property
    def publish_detail(self):
        return {'id': self.publish.pk, 'name': self.publish.name, 'addr': self.publish.addr}  # 方法返回的是什么字段的value就是什么

    @property
    def author_list(self):
        lis = []
        for i in self.author.all():
            lis.append({'id': i.pk, 'name': i.name, 'phone': i.phone})
        return lis

多表关联反序列化保存

# 序列化和反序列化,用的同一个序列化类
    -序列化的字段有:name,price ,   publish_detail,author_list
    -反序列化字段:name,price    ,publish,author

反序列化之保存

视图类

class BookView(APIView):
    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})

序列化类

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
        extra_kwargs = {
            'title': {'max_length': 8},  # 这种可序列化也可反序列化
            'publish': {'write_only': True},  # 这俩只用来反序列化
            'author': {'write_only': True},
        }

    publish_detail = serializers.DictField(read_only=True)  # 这俩只用来序列化
    author_list = serializers.ListField(read_only=True)

反序列化之修改

视图类

class BookDetailView(APIView):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '修改成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})

序列化类

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
        extra_kwargs = {
            'title': {'max_length': 8},  # 这种可序列化也可反序列化
            'publish': {'write_only': True},  # 这俩只用来反序列化
            'author': {'write_only': True},
        }

    publish_detail = serializers.DictField(read_only=True)  # 这俩只用来序列化
    author_list = serializers.ListField(read_only=True)

反序列化字段校验其他

# 视图类中调用:ser.is_valid()---》触发数据的校验
	-4层
    	-字段自己的:max_length,required。。。
        -字段自己的:配合一个函数name = serializers.CharField(max_length=8,validators=[xxx])
        -局部钩子
        -全局钩子

ModelSerializer使用

# 之前学的继承Serializer得序列化类,与表模型没有必然的联系,既可序列化A类又可序列化B类
# 现在学的继承了ModelSerialize的序列化类是与表模型一一对应的,用法基本一致
    1 写序列化类,继承ModelSerializer
    2 在序列化类中,再写一个类,必须叫
    	class Meta:
			model=表模型
             fields=[] # 要序列化的字段
    3 可以重写字段,一定不要放在class Meta的下面
    	-定制字段,跟之前讲的一样
    4 自定制的字段,一定要在fields中注册一下
    5 class Meta: 有个extra_kwargs,为某个字段定制字段参数
    6 局部钩子,全局钩子,完全一致
    7 大部分请情况下,不需要重写 create和update了

Book的5个接口

表模型

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.IntegerField()

    publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
    author = models.ManyToManyField(to='Author')

    @property
    def publish_detail(self):
        return {'id': self.publish.pk, 'name': self.publish.name, 'addr': self.publish.addr}

    @property
    def author_list(self):
        lis = []
        for i in self.author.all():
            lis.append({'id': i.pk, 'name': i.name, 'phone': i.phone})
        return lis

视图类

class BookView(APIView):
    def get(self, request):
        book = Book.objects.all()
        ser = BookSerializer(instance=book, many=True)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})


class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '修改成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response('')

序列化类

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
        extra_kwargs = {
            'title': {'max_length': 8},
            'publish': {'write_only': True},
            'author': {'write_only': True},
        }

    publish_detail = serializers.DictField(read_only=True)
    author_list = serializers.ListField(read_only=True)

Publish的5个接口

表模型

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

视图类

class PublishView(APIView):
    def get(self, request):
        publish = Publish.objects.all()
        ser = PublishSerializer(instance=publish, many=True)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def post(self, request):
        ser = PublishSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})


class PublishDetailView(APIView):
    def get(self, request, pk):
        publish = Publish.objects.filter(pk=pk).first()
        ser = PublishSerializer(instance=publish)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def put(self, request, pk):
        publish = Publish.objects.filter(pk=pk).first()
        ser = PublishSerializer(instance=publish, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '修改成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})

    def delete(self, request, pk):
        Publish.objects.filter(pk=pk).delete()
        return Response('')

序列化类

class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = '__all__'

Author的5个接口

表模型

class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.IntegerField()

    author_detail = models.OneToOneField(to='Author_detail', on_delete=models.CASCADE)

    # @property  # 此处注释是因为有种写的方法,一是使用source进行关联查询,二是使用此方法进行字段的定制
    # def email(self):
    #     return self.author_detail.email
    #
    # @property
    # def age(self):
    #     return self.author_detail.age


class Author_detail(models.Model):
    email = models.CharField(max_length=32)
    age = models.IntegerField()

视图类

class AuthorView(APIView):
    def get(self, request):
        author = Author.objects.all()
        ser = AuthorSerializer(instance=author, many=True)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def post(self, request):
        ser = AuthorSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})


class AuthorDetailView(APIView):
    def get(self, request, pk):
        author = Author.objects.filter(pk=pk).first()
        ser = AuthorSerializer(instance=author)
        return Response({'code': 200, 'msg': '成功', 'data': ser.data})

    def put(self, request, pk):
        author = Author.objects.filter(pk=pk).first()
        ser = AuthorSerializer(instance=author, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 200, 'msg': '修改成功'})
        else:
            return Response({'code': 201, 'msg': ser.errors})

    def delete(self, request, pk):
        Author.objects.filter(pk=pk).delete()
        return Response('')

序列化类

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ['name', 'phone', 'email', 'age']
        extra_kwargs = {
            'name': {'max_length': 8},
        }

    email = serializers.CharField(source='author_detail.email')
    age = serializers.IntegerField(source='author_detail.age')

    def create(self, validated_data):
        author_detail_value = validated_data.pop('author_detail')
        try:
            with transaction.atomic():
                author_detail = Author_detail.objects.create(**author_detail_value)
                validated_data['author_detail'] = author_detail
                author = Author.objects.create(**validated_data)
        except Exception as e:
            print(e)
            transaction.rollback()
        # author_detail =   Author_detail.objects.create(email=validated_data['email'], age=validated_data['age'])
        # author = Author.objects.create(name=validated_data['name'], phone=validated_data['phone'], author_detail=author_detail)
        # 虽然可以这么写但是,比较麻烦而且字段多了不好操作
        return author

    def update(self, author, validated_data):
        author_detail = author.author_detail
        author_detail_value = validated_data.pop('author_detail')
        try:
            with transaction.atomic():
                for i in validated_data:
                    setattr(author, i, validated_data[i])
                for i in author_detail_value:
                    setattr(author_detail, i, author_detail_value[i])
        except Exception as e:
            print(e)
            transaction.rollback()
        else:
            author.save()
            author_detail.save()
        return author

标签:ModelSerializer,ser,author,detail,publish,用法,序列化,data
From: https://www.cnblogs.com/juzixiong/p/17413095.html

相关文章

  • yum的基础常用用法
    yum的安装与配置以Centos7.x为例,检查yum是否已经安装,执行如下命令:rpm-qa|grepyum如果没有任何显示,表示系统中还没有安装yum工具,yum安装包在Centos系统光盘中可以找到,执行如下指令进行安装:rpm-ivhyum-*.noarch.rpm安装yum需要python-elementtree、python-sqlite、urlgrabb......
  • 滑动窗口的极值与deque用法
    在程序设计中,为了优化算法可能会用到滑动窗口或者双指针的思想,这种算法能够蛮力情况下的复杂度\(O(n^2)\)降低为线性。滑动窗口的问题通常可以用双指针来解决,即用头尾两个指针来约束窗口大小。网上对于这两个名词的定义和解释莫衷一是。个人理解,固定一段窗口/区间大小而衍生的问......
  • Weblogic < 10.3.6 'wls-wsat' XMLDecoder 反序列化漏洞(CVE-2017-10271)
    参考:https://github.com/vulhub/vulhub/blob/master/weblogic/CVE-2017-10271/README.md反弹shellEXP:POST/wls-wsat/CoordinatorPortTypeHTTP/1.1Host:172.31.14.123:7001Accept-Encoding:gzip,deflateAccept:*/*Accept-Language:enUser-Agent:Mozilla/5.0(com......
  • table常用用具函数 - list用法
     table_listext.luafunctionlist.reset(listTb,val)fori=1,#listTbdolistTb[i]=valendendfunctionlist.castItemToNum(listTb)fori=1,#listTbdolistTb[i]=tonumber(listTb[i])endreturnlistTbendfunctionlis......
  • table常用工具函数 - 表用法
     table_ext.lua---如果table不为空则新建functiontable.getEmptyTable(tb)ifnil==tbornil~=next(tb)thenreturn{}endreturntbendfunctiontable.isEmpty(tb)returnnil==tbornil==next(tb)endfunctiontable.swap(tb,k1......
  • drf-序列化组件
    目录作业讲解1Request类源码分析1.1总结的知识点1.2源码分析1.2APIView+Response写个接口2序列化组件介绍3序列化类的基本使用3.1查询所有和查询单条4常用字段类和参数(了解)4.1常用字段类4.2字段参数(校验数据来用的)5反序列化之校验6反序列化之保存75个接口代码路由......
  • 【hadoop】 3005-hadoop对象序列化编码
    一、hadoop序列化操作Writable接口,是根据 DataInput 和 DataOutput 实现的简单、有效的序列化对象MR的任意Key和Value必须实现Writable接口.MR的任意key必须实现WritableComparable接口二、自定义Writable,实现MapReduce程序1、需求内容日期 ......
  • jcmd常用用法
    jvmcommand用于将诊断命令请求发送到正在运行的java虚拟机,从jdk7开始提供。是一个功能全面的工具,可用于获取目标java进程的性能统计,jfr,内存使用,垃圾收集,线程堆栈,jvm运行时间。C:\Users\user>jcmd-hUsage:jcmd<pid|mainclass><command...|PerfCounter.print|-ffile>o......
  • 18、什么是 java 序列化?什么情况下需要序列化?
    序列化就是一种用来处理对象流的机制。将对象的内容流化,将流化后的对象传输于网络之间。序列化是通过实现serializable接口,该接口没有需要实现的方法,implementSerializable只是为了标注该对象是可被序列化的,使用一个输出流(FileOutputStream)来构造一个ObjectOutputStream对象,接......
  • Request类的源码分析和序列化与反序列化
    Request类的源码分析和序列化与反序列化Request类源码分析#源码分析: self._request=request#将老的request传给_requestdef__getattr__(self,attr):try:returngetattr(self._request,attr)#在老的request中找attr找到了就返回这个方法......