drf--source/定制字段的两种方式/反序列化保存/字段校验其他/ModelSerializer

序列化高级用法之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')

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

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

序列化类中写

### 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
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

多表关联反序列化保存

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

反序列化之保存

视图类

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

反序列化之修改

视图类

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

反序列化字段校验其他

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

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了
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值