首页 > 其他分享 >drf4

drf4

时间:2023-02-02 19:33:24浏览次数:40  
标签:serializers name author publish CharField drf4 序列化

今日内容概要

  • 序列化类常用字段和字段参数
  • 序列化高级用法之source
  • 序列化高级用法之定制字段的两种方式
  • 多表关联反序列化保存
  • 反序列化字段校验其他
  • ModelSerializer使用

今日内容详细

序列化类常用字段和字段参数

image

序列化类中的字段类和模型层中的字段类型类似 并且也可以传参数
具体看图

需要记住的主要有:
	CharField						字符串字段
	IntegerField					整型字段
	DecimalField					浮点型字段
	DateTimeField					时间字段
	BooleanField					布尔字段

以及序列化类中独有的字段
	ListField
	DictField

字段参数:
	1.CharField及其子类的参数---->反序列化的校验 字段自己的规则
		max_length				最大长度
		min_lenght				最小长度
		allow_blank				是否允许为空
		trim_whitespace			是否截断空白字符
	2.IntegerField的参数
		max_value				最小值
		min_value				最大值
	3.所有字段类都有的参数
		required				表明该字段在反序列化时必须输入 默认True
		default					反序列化时使用的默认值
		allow_null				表名该字段是否允许传入None 默认False
		validators				该字段使用的验证器
		----了解即可----
		error_messages			包含错误编号与错误信息的字典
		label					用于HTML展示API页面时 显示的字段名称
		help_text				用于HTML展示API页面时 显示的字段帮助提示信息
		----序列化类中的重点----
		read_only				表明该字段仅用于序列化输出 默认False
		write_only				表明该字段仅用于反序列化输入 默认False


反序列化校验执行流程
	1.先执行字段自己的校验规则 如最大长度 最短长度等等
	2.validators中的校验规则
		如: name = serializers.CharField(validators=[函数名,])
	3.局部钩子校验规则
	4.全局钩子校验规则

序列化高级用法之source

先创建表
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    author = models.ManyToManyField(to='Author')

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)
    phone = models.CharField(max_length=11)

    
source可以指定序列化字段的名字
class BookSerializer(serializers.Serializer):
    # 字段参数 通用的,所有字段都可以写  通过source指定哪个字段
    # 自有字段 直接写字段名字
    name_real = serializers.CharField(max_length=8, source='name')
    real_price = serializers.CharField(source='price')

    # 关联字段 一对多的关联,直接点
    publish = serializers.CharField(source='publish.name')

    #多对多 source不能用 无法直接取到所需的数据
    authors=serializers.CharField(source='authors.all')

序列化高级用法之定制字段的两种方式

'''方式一: 使用SerializerMethodField定制'''
可以定制关联字段的显示形式
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()

    # 定义一个字段 使用SerializerMethodField
    publish_detail = serializers.SerializerMethodField()
    # 定义一个函数 函数名必须是 get_自定义的字段名 并传入一个对象
    def get_publish_detail(self, obj):
        # 一对多的表关系返回一个字典
        return {'name': obj.publish.name, 'addr': obj.publish.addr}

    author_list = serializers.SerializerMethodField()

    def get_author_list(self, obj):
        # 多对多的表关系返回一个列表套字典
        return [{'name': author.name, 'phone': author.phone}for author in obj.author.all()]

'''方式二: 在表模型中定制'''
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    author = models.ManyToManyField(to='Author')
    # 函数名与序列化类中的字段名一致
    def publish_detail(self):
        return {'name': self.publish.name, 'addr': self.publish.addr}
    # 函数名与序列化类中的字段名一致
    def author_list(self):
        return [{'name': author.name, 'phone': author.phone} for author in self.author.all()]

序列化类中
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()
    # 字典使用DictField字段 字段名与模型层中的函数名一致
    publish_detail = serializers.DictField()
    # 列表使用ListField字段 字段名与模型层中的函数名一致
    author_list = serializers.ListField()

多表关联反序列化保存

'''新增一个创建图书接口'''
--前端传入的数据格式: {name:红楼梦,price:19,publish:1,authors:[1,2]}

视图类
class BookView(APIView):
    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功'})
        return Response({'code': 101, 'msg': ser.errors})

序列化类
class BookSerializer(serializers.Serializer):
    # name和price字段既用来序列化也用来反序列化
    name = serializers.CharField()
    price = serializers.CharField()
    # publish_detail和author_list只用来做序列化 所以添加一个字段参数read_only=True
    publish_detail = serializers.DictField(read_only=True)
    author_list = serializers.ListField(read_only=True)
    # 新增两个反序列化字段 并且是只写的 添加字段参数write_only=True
    # 书只能有一个出版社 所以前端传过来的只有一个 无需用字典字段
    publish = serializers.CharField(write_only=True) 
    author = serializers.ListField(write_only=True)

    # 重写create方法
    def create(self, validated_data):
        # 分别取到对应参数 新增一本书
        book = models.Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'), publish_id=validated_data.get('publish'))
        # 多对多第三张表是自动创建的 可以使用add方法将传入的作者打散写入到第三张表中
        book.author.add(*validated_data.get('author'))
        return book

'''修改图书接口'''

视图类
class BookDetail(APIView):
    def put(self, request, pk):
        book = models.Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功'})
        return Response({'code': 101, 'msg': ser.errors})

序列化类
class BookSerializer(serializers.Serializer):
    def update(self, instance, validated_data):
        # 可以使用for循环 也可以一条条取出修改
        for new, params in validated_data.items():
            if new == 'publish':
                new += '_id'
            elif new == 'author':
                # 可以先将原本的关系清空再add添加
                instance.author.clear()
                instance.author.add(*params)
                continue
            # 利用反射来修改
            setattr(instance, new, params)
        instance.save()
        return instance

反序列化字段校验其他

总共四层
	1.字段自己的 如: name = serializer.CharField(max_length=8)
	2.validators=[方法,]
	3.局部钩子
	4.全局钩子

ModelSerializer的使用

ModelSerializer继承自Serializer 帮我们节省了很多的操作
使用它的话序列化类和表模型是强关联的 只能序列化指定表
并且大部分请求都不需要手动写create和update方法了

固定写法

class 序列化类名(serializer.ModelSerializer):
    class Meta:
        model = 关联的表模型
        fields = [序列化的字段,...] # '__all__'表示序列化表中所有的字段
        # 当需要定制反序列化的字段时 可以在extra_kwargs中添加字段属性 或者重写 与Meta类同级
        extra_kwargs = {字段名:{字段属性:值},...}

    # 局部钩子和全局钩子的使用方法和之前一致

举例:
    
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'author']
        extra_kwargs = {'name': {'max_length': 8},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True},
                        'publish': {'write_only': True},
                        'author': {'write_only': True}}
    def validate_name(self, name):
        if name.startswith('鸡'):
            raise ValidationError('不能鸡开头')
        return name

标签:serializers,name,author,publish,CharField,drf4,序列化
From: https://www.cnblogs.com/lzjjjj/p/17087195.html

相关文章