django序列化器使用介绍

继上篇讲了django orm表建立,那不得不再讲一下django(drf)序列化serializer

一、序列化有什么用?

1.1、serializer序列化分为两种:正向序列化(序列化)&反向序列化(反序列化)

  • 序列化即将数据库对象转换成数据,可实现数据的可视化输出以及更为高级的定制化输出
  • 反序列化即将数据转换成序列化对象,进而将其存入数据库,可实现字段的校验(drf序列化器字段类型及参数)

1.2、无论是序列化还是反序列化既可以使用SerializerMethodField也可以使用ModelSerializer

  • 引入方式from rest_framework.serializers import Serializer,ModelSerializer

二、操作模式

2.1、Serializer序列化

# 以AuthorDetail表为例子
def phone_rule(data):  # data就是字段tel对应的数据
    """自定义手机号验证规则"""
    pass

class AuthorDetailSercodializer(Serializer):
    id = serializers.IntegerField(label="主键", read_only=True, error_messages={"required": "read_only为真,表示此字段只在序列化时做检查,反序列化不做检查"})
    addr = serializers.CharField(label="住址", error_messages={"required": "地址字段addr不能为空"})
    tel = serializers.IntegerField(label="联系方式", error_messages={"required": "联系方式字段tel不能为空"}, validators=[phone_rule, ])

	#使用Serializer时候必须重写create方法
	def create(self, validated_data):
		# validated_data.pop("key")
		res = models.AuthorDetail.objects.create(**validated_data)
		return res

	# 使用Serializer时候必须重写update方法
	def update(self, instance, validated_data):
		try:
			models.AuthorDetail.objects.filter(pk=instance.id).update(**validated_data)
			return {"code": 200, "msg": "成功"}
		except Exception as e:
			return {"code": 400, "msg": "失败", "error": e}
	
	# 可以写局部钩子对部分字段校验,函数命名规则"validate_字段名"
	def validate_tel(self, data):
		pass
		
	# 也可以写全局钩子,函数命令规则validate
	def validate(self, attr):  # 先校验局部再校验全局钩子
		# addr = attr.get("addr")
		# tel = attr.get("tel")
		pass

2.2、ModelSerializer序列化

# 以Author表为例
class AuthorSerializer(ModelSerializer):
    class Meta:
        model = models.Author
        
        # --------------------------------------START序列化字段介绍--------------------------------
        # 指定序列化字段方式一(2选1):
        # fields = ["id", "name", "age", "author_detail"]  # 因books是Authoro类里面的一个属性,不是字段

        # 指定序列化字段方式二(2选1):
        field = "__all__"
        # 剔除部分字段不显示(只能在序列化字段方式一使用,即只与field配合使用)
        # exclude = ["name", "author_detail"]  
        exclude = []
        # --------------------------------------END序列化字段介绍--------------------------------
        
        # 深度:假设C表关联B表,B表关联A表,对应关系均为一对多:A-B,B-C。深度1即序列化C表会触及到B表,深度2即序列化C表不仅会触及到B表还会由此触及到A表
        depth = 1
        
	# 可以写局部钩子对部分字段校验,函数命名规则"validate_字段名"
	def validate_tel(self, data):
		pass
		
	# 也可以写全局钩子,函数命令规则validate
	def validate(self, attr):  # 先校验局部再校验全局钩子
		# addr = attr.get("addr")
		# tel = attr.get("tel")
		pass

三、如何在序列化中增加自定义字段?

3.1、增加自定义字段方式一source:依赖于已有字段。序列化正常调用,反序列化不执行。正反序列化类可合二为一

# 参照2.1,采用Serializer序列化
customField = serializers.CharField(error_messages={"required": "自定义字段,取值来源于source,即addr值"}, read_only=True, source="addr")
# 参照2.2,采用ModelSerializer序列化
customField = serializers.CharField(error_messages={"required": "自定义字段,取值来源于source,即name值"}, read_only=True, source="name")

3.2、增加自定义字段方式二SerializerMethodField:序列化正常调用,反序列化不执行。正反序列化类可合二为一

# 参照2.1,采用Serializer序列化
customField = serializers.SerializerMethodField()
def get_customField(self, obj):
    return {"name2.1": "测试序列化自定义新增字段"}
# 参照2.2,采用ModelSerializer序列化
customField = serializers.SerializerMethodField()
def get_customField(self, obj):
    return {"name2.2": "测试序列化自定义新增字段"}

3.3、增加自定义字段方式三PrimaryKeyRelatedField:只有是外键字段才可以使用PrimaryKeyRelatedField进行增加自定义字段操作。序列化正常调用,反序列化不执行。正反序列化类可合二为一

# 以Book表为例子,采用Serializer序列化
class BookSerializers(Serializer):
    id = serializers.IntegerField(label="主键", read_only=True, error_messages={"required": "read_only为真,表示此字段只在序列化时做检查,反序列化不做检查"})
    name = serializers.CharField(label="书名", error_messages={"required": "书名字段name不能为空"})
    price = serializers.DecimalField(label="价格", max_digits=6, decimal_places=2, error_messages={"required": "价格字段price不能为空"})
    publish = serializers.PrimaryKeyRelatedField(label="出版社", queryset=models.Book.objects.all(), error_messages={"required": "出版社ID字段publish不能为空"})  # 可以增加属性default=models.Book.objects.first().id

	# 调通用方法:对结果publish="主键id" 格式化 返回publish模型数据
    def to_representation(self, obj):  # 此函数在序列化时才会用到,用于自定义输出
        ret = super(BookSerializers, self).to_representation(obj)
        ret["publish"] = {
            "name": obj.publish.name,
            "addr": obj.publish.addr
        }
        return ret
# 以Book表为例子,采用ModelSerializer序列化
class BookSerializers(ModelSerializer):
    class Meta:
        model = models.Book
        field = "__all__"
        exclude = []
    # 重新publish赋值
    publish = serializers.PrimaryKeyRelatedField(label="出版社", queryset=models.Book.objects.all(), error_messages={"required": "出版社ID字段publish不能为空"})  # 可以增加属性default=models.Book.objects.first().id

	# 调通用方法:对结果publish="主键id" 格式化 返回publish模型数据
    def to_representation(self, obj):  # 此函数在序列化时才会用到,用于自定义输出
        ret = super(BookSerializers, self).to_representation(obj)
        ret["publish"] = {
            "name": obj.publish.name,
            "addr": obj.publish.addr
        }
        return ret

3.4、增加自定义字段方式四"继承自身":只可用于正向序列化即不可以在反序列化中使用。正反序列化类不可合二为一

# 以Book表为例子,publish字段继承于Publish序列化,采用Serializer序列化
class PublishSerializers(Serializer):
    id = serializers.IntegerField(label="主键", read_only=True, error_messages={"required": "read_only为真,表示此字段只在序列化时做检查,反序列化不做检查"})
    name = serializers.CharField(label="出版社名", error_messages={"required": "出版社字段name不能为空"})
    addr = serializers.CharField(label="地址", error_messages={"required": "地址字段addr不能为空"})
    # book_set = serializers.StringRelatedField(many=True)  # book_set为反向查询名称,通过这个可以将反向数据导出,不常用哟,不做过多描述,了解即可

class BookSerializers(Serializer):
    id = serializers.IntegerField(label="主键", read_only=True, error_messages={"required": "read_only为真,表示此字段只在序列化时做检查,反序列化不做检查"})
    name = serializers.CharField(label="书名", error_messages={"required": "书名字段name不能为空"})
    price = serializers.DecimalField(label="价格", max_digits=6, decimal_places=2, error_messages={"required": "价格字段price不能为空"})
    publish = PublishSerializers(many=False)
# 以Book表为例子,publish字段继承于Publish序列化, 采用ModelSerializer序列化
class PublishSerializers(ModelSerializer):
    class Meta:
        model = models.Publish
        field = "__all__"
        exclude = []
    # book_set = serializers.StringRelatedField(many=True)  # book_set为反向查询名称,通过这个可以将反向数据导出,不常用哟,不做过多描述,了解即可

class BookSerializers(ModelSerializer):
    class Meta:
        model = models.Book
        field = "__all__"
        exclude = []
    # 重新publish赋值
    publish = PublishSerializers(many=False)

四、调用方式

  • 假设数据库表为A,序列化类|反序列化类均为ASerializers,反序列化数据dataDict = {“name”: “test”}

4.1、序列化

obj = models.A.objects.get(id=1)
# objs = models.A.objects.all()
objSr = ASerializers(instance=obj)  # 检查objSr的属性data
# objSr = ASerializers(instance=objs, many=True)
print(objSr.data)

4.2、反序列化

  • 添加数据
objSr = ASerializers(data=dataDict)
# objSr.is_valid(raise_exception=True)
objSr.is_valid()  # 反序列时必须执行is_valid方法。校验成功,则数据为objSr.validated_data;校验失败,错误信息在objSr.errors中,同时属性validated_data为{}
print(objSr.validated_data)
objSr.save()  # 会自动跳转到重写的方法create中
  • 更新数据
obj = models.A.objects.get(pk=1)
objSr = ASerializers(instance=obj, data=dataDict)
# objSr.is_valid(raise_exception=True)
objSr.is_valid()  # 反序列时必须执行is_valid方法。校验成功,则数据为objSr.validated_data;校验失败,错误信息在objSr.errors中,同时属性validated_data为{}
print(objSr.validated_data)
objSr.save()  # 会自动跳转到重写的方法update中

你可能感兴趣的:(web后端,python,代码,django,python,后端)