首页 > 其他分享 >Day04 drf之source序列化字段定制与反序列化校验、modelserializer使用

Day04 drf之source序列化字段定制与反序列化校验、modelserializer使用

时间:2023-05-19 20:26:37浏览次数:44  
标签:modelserializer name author self detail Day04 serializers 序列化

今日内容

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

# 1 创建了5个表(图书管理的5个)
# 2 对booke进行序列化


# 总结:source的用法
	-1 修改前端看到的字段key值---》source指定的必须是对象的属性
    	book_name = serializers.CharField(source='name')
    -2 修改前端看到的value值,---》source指定的必须是对象的方法
    	表模型中写方法
          def sb_name(self):
        	return self.name + '_sb'
        序列化类中
        	book_name = serializers.CharField(source='sb_name')
            
     -3 可以关联查询(得有关联关系)
    	publish_name = serializers.CharField(source='publish.name')

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

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

2.1 序列化类中写

### 2。1 定制字段方式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.2 表模型中写

###### ###### ###### ###### ###### 序列化类###### ###### ###### ###### 
### 2.2 定制字段方式2
class BookSerialzier(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    # 1 序列化类中这样写
    # 2 到表模型中写一个方法,方法名必须叫 publish_detail,这个方法返回什么,这个字段的value就是什么
    publish_detail = serializers.DictField()

    author_list=serializers.ListField()
    
    
###### ###### ###### ###### ###### 表模型###### ###### ###### ###### 
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
    authors = models.ManyToManyField(to='Author')

    def sb_name(self):
        return self.name + '_sb'

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

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


3 多表关联反序列化保存

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

3.1 反序列化之保存

视图类

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

序列化类

class BookSerialzier(serializers.Serializer):
    # 即用来做序列化,又用来做反序列化
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()

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

    # 这俩,只用来做反序列化
    publish_id = serializers.IntegerField(write_only=True)
    authors = serializers.ListField(write_only=True)

    def create(self, validated_data):  # {name:西游记,price:88,publish:1,authors:[1,2]
        authors = validated_data.pop('authors')
        book = Book.objects.create(**validated_data)
        book.authors.add(*authors)
        book.save()
        return book

3.2 反序列化之修改

视图类

class BookDetailView(APIView):

    def put(self, request,pk):
        book=Book.objects.get(pk=pk)
        ser = BookSerialzier(data=request.data,instance=book)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '更新成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

序列化类

class BookSerialzier(serializers.Serializer):
    # 即用来做序列化,又用来做反序列化
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()

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

    # 这俩,只用来做反序列化
    publish_id = serializers.IntegerField(write_only=True)
    authors = serializers.ListField(write_only=True)


    def update(self, instance, validated_data):
        authors = validated_data.pop('authors')
        for item in validated_data:
            setattr(instance, item, validated_data[item])
        instance.authors.set(authors)
        instance.save()
        return instance

4 反序列化字段校验其他

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

5 ModelSerializer使用

# 之前写的序列化类,继承了Serializer,写字段,跟表模型没有必然联系
class XXSerialzier(Serializer)
	id=serializer.CharField()
	name=serializer.CharField()
    
 XXSerialzier既能序列化Book,又能序列化Publish


# 现在学的ModelSerializer,表示跟表模型一一对应,用法跟之前基本类似

	1 写序列化类,继承ModelSerializer
    2 在序列化类中,再写一个类,必须叫
    	class Meta:
			model=表模型
             fields=[] # 要序列化的字段
    3 可以重写字段,一定不要放在class Meta
    	-定制字段,跟之前讲的一样
    4 自定制的字段,一定要在fields中注册一下
    5 class Meta: 有个extra_kwargs,为某个字段定制字段参数
    6 局部钩子,全局钩子,完全一致
    7 大部分请情况下,不需要重写 create和update了
    

作业

# 1 book上课讲的也写一遍
#2  Publish的5个接口,ModelSerializer写
 
    
# 3 author的5个接口(写不出来没关系)(
-新增或修改author时,把author_detail的内容也新增进去
    

model层

from django.db import models


# Create your models here.

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

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

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

    authors = models.ManyToManyField(to='Author')

    def authors_detail(self):
        l = []
        for author in self.authors.all():
            l.append({'name': author.name, 'age': author.age, 'email': author.auth_detail.email,
                      'phone': author.auth_detail.phone})
        return l
    # def author_detail(self):
    #     return {'id':self.authors,'name':self.authors.name}


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


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.CharField(max_length=32)
    auth_detail = models.OneToOneField(to='AuthorsDetail', on_delete=models.CASCADE)


class AuthorsDetail(models.Model):
    email = models.CharField(max_length=32)
    phone = models.BigIntegerField()

view层

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book, Publish, Author
from app01.bookSerializer import BookSerializer, PublishSerializer, AuthorSerializer

class AuthView(APIView):
    def get(self, request):
        auth = Author.objects.all()
        ser = AuthorSerializer(instance=auth, many=True)
        return Response({'code': 100, 'msg': 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': 100, 'msg': ser.errors})


class AuthDetailView(APIView):
    def get(self, request, pk):
        author = Author.objects.get(pk=pk)
        ser = AuthorSerializer(instance=author)
        return Response({'code': 100, 'msg': ser.data})

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

    def delete(self, request, pk):
        Author.objects.filter(pk=pk).delete()
        return Response({'code': 200, 'msg': '删除成功'})

serializer层

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ['name', 'age', 'email', 'phone', 'id', 'detail_email', 'detail_phone', 'auth_detail']
        extra_kwargs = {
            'auth_detail': {'read_only': True}
        }

    # auths_detail = serializers.DictField(read_only=True)
    # 只读
    email = serializers.CharField(source='auth_detail.email', read_only=True)
    phone = serializers.IntegerField(source='auth_detail.phone', read_only=True)

    # 只写
    detail_email = serializers.CharField(write_only=True)
    detail_phone = serializers.IntegerField(write_only=True)

    def create(self, validated_data):
        author_detail_obj = AuthorsDetail.objects.create(phone=validated_data.get('detail_phone'),
                                                         email=validated_data.get('detail_email'))
        author_obj = Author.objects.create(name=validated_data.get('name'), age=validated_data.get('age'),
                                           auth_detail_id=author_detail_obj.pk)
        return author_obj

    def update(self, instance, validated_data):
        print(validated_data)
        # print(instance.__dict__)
        instance.name = validated_data['name']
        instance.age = validated_data['age']
        instance.save()
        auth_detail = instance.auth_detail
        auth_detail.email = validated_data['detail_email']
        auth_detail.phone = validated_data['detail_phone']
        auth_detail.save()
        return instance

标签:modelserializer,name,author,self,detail,Day04,serializers,序列化
From: https://www.cnblogs.com/yedayangboke/p/17416176.html

相关文章

  • 模块与包,反序列化源码解析,drf请求响应,视图组件两个视图基类
    0模块与包的使用#模块与包 -模块:一个py文件,被别的py文件导入使用,这个py文件称之为模块,运行的这个py文件称之为脚本文件-包:一个文件夹下有__init__.py#模块与包的导入问题 '''0导入模块有相对导入和绝对导入,绝对的路径是从环境变量开始的1......
  • drf之反序列化校验源码分析 、 断言 、drf之请求和响应
    目录一、反序列化校验源码分析入口:总结:二、断言三、drf之请求3.1Request类对象的分析.data.query_params其他的属性用起来跟之前一样3.2请求,能够接受的编码格式限制只能接受某种或某几种编码格式限制方式一:在视图类上写---》只是局部视图类有效限制方式二:在配置文件中写---》全......
  • java中把对象序列化成php序列化的字符串以及把php序列化的字符串反序列化为java对象的
    依赖第三方库phprpc序列化成php格式的字符串很简单,直接调用org.phprpc.util.PHPSerializer.serializer方法就行,有问题的是反序列化php格式的字符串为List或Map对象时,得到的是个AssocArray对象,需要写方法进行转换。通过下面这个方法可以实现转为java对象。publicstati......
  • uni.request(OBJECT)前端post请求数据json序列化
    一、uni-app前端post请求数据json序列化1.前置须知Content-Type实体头部用于指示资源的MIME(媒体)类型mediatype。在响应中,Content-Type标头告诉客户端实际返回的内容的内容类型。在请求中,客户端告诉服务器实际发送的数据类型。2.uni.request({})官方文档2.1dat......
  • drf——序列化之source(了解)、定制字段的两种方式(重要)、多表关联反序列化保存、反
    1序列化高级用法之source(了解)#1.创建了5个表(图书管理的5个)#2.对book进行序列化#总结:source的用法 1.修改前端看到的字段key值--->source指定的必须是对象的属性 book_name=serialiazers.CharField(source='name')2.修改前端看到的value值--->source指......
  • linux学习day04(shell学习)
    shell是一个命令执行器,作用是遵循一定的语法将输入的命令加以解释并传给系统,用户可以用shell来启动、挂起、停止甚至是编写一些程序。shell是用户和linux的桥梁,定义了各种变量和参数,并提供了很多在高阶语言中才具有的控制结构,包括循环和分支,虽然他不是内核的一部分,但是她调用了系......
  • 序列化高级用法之source,序列化高级用法之定制字段的两种方式,多表关联反序列化保存,反序
    序列化高级用法之source:source的用法:1修改前端看到的字段key值---》source指定的必须是对象的属性: 前端展示效果: 2. 修改前端看到的value值,---》source指定的必须是对象的方法models中: 序列化类中: 前端展......
  • 序列化的高级用法与ModelSerializer的使用
    序列化的高级用法与ModelSerializer的使用序列化高级用法之source(了解)source的三个用法:1.取别名: book_name=serializers.CharField(source='name')#book_name为前端可以看到的字段值,name是对象真实的属性。注意:别名和真实属性不能相同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......
  • drf-序列化组件
    目录作业讲解1Request类源码分析1.1总结的知识点1.2源码分析1.2APIView+Response写个接口2序列化组件介绍3序列化类的基本使用3.1查询所有和查询单条4常用字段类和参数(了解)4.1常用字段类4.2字段参数(校验数据来用的)5反序列化之校验6反序列化之保存75个接口代码路由......