serializer只需要定义好字段即可(序列化器的字段名称和对应的对象的字段想对应),任何方法都是非必须的。
序列化
s = XXSerializer(instance)
s.data # 获得原生python数据
# 可以通过 JSONRenderer来获得JSON格式的数据
json = JSONRenderer().render(serializer.data)
逆序列化
data = JSONRenderer.parse(stream) # 获得原生python数据
serializer = XXSerializer(data=data)
serializer.is_valid()
serializer.validated_data
可以通过定义create update来实现实例的保存
def create(self, validated_data):
return XX.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.save()
return instance
在获得serializer之后,通过调用save来保存,校验一些参数,根据构造时是否传入了instance来分别调用create或update,serializer.save()还可接受参数,这些参数会传递到validated_data中,这样在create和update中可以使用,此外,还可以直接重载save函数
验证
需要先调用is_valid才能获得serializer的validated_data或调用save。如果在逆序时验证失败则可查看其errors属性。
serializer.error
# dict 其中的每个key值是字段名称,值为错误原因(list)
# 另有non_filed_error指明通用错误,可以通过NON_FIELD_ERRORS_KEY来设置该键值的名称
# 如果是list的错误返回的是list的dict
另对于is_valid方法,可以接受raise_exception参数来指示是否抛出异常。
field-level validation
对应字段的validate函数,需要返回接受的参数(可以为处理后的值 不需要为原值)或者触发异常
title = serializer.CharField()
def validate_title(self, value):
if not:
raise serializers.ValidationError("err msg")
return value
object-level validation
需要同时获取多个字段的校验
def validate(self, data):
# data就是接受的参数字典
return data
validators
可以抽象出检查函数,在声明字段时包含即可
score = IntegerField(validators=[Uni])
也可以在类的Meta中包含validatiors,这样每个字段都会进行校验
class EventSerial.....
class Meta:
validators = Uni....
获取初始值
当传入的是对象,想要序列化时,可以获取instance,即初始值。
当传入的是数据,想要逆序列化,可以获取Initial_data,即初始值。
部分更新
需要在创建序列化器时额外传入partial=True
nested serializer
可以把一个serializer作为另一个的field加入
serializer本身也是field的子类
加required=False则需要可接收None
和many=True参数则为包含多个值的列表
在具体构造时:
serializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})
# {'user': {'email': ['Enter a valid e-mail address.']}, 'created': ['This field is required.']}
构造完成后,validated_data 同样包含嵌入的serializer
注意重载create函数和update函数
multiple objects
支持序列化 可传入many=True,但是不支持逆序劣化,需要使用ListSerializer
context
往serializer中传入额外的信息
s = AccountSerializer(account, context={'request': request})
使用时可通过self.context来获得 但是不会出现在输出中