欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > DRF序列化_data传参

DRF序列化_data传参

2024/10/24 19:17:11 来源:https://blog.csdn.net/shujufenxishi/article/details/141641438  浏览:    关键词:DRF序列化_data传参

DRF序列化_data传参

  • 1. 调用 ser_data .is_valid()
  • 2、ser_data .is_valid() 验证总结
  • 3、验证完后,获取 ser_data .data,
  • 4、验证完后可以直接获取 validated_data ,因为校验之前,已经序列化过了,没有必要再调data了

instance传参时,序列化不能对数据进行校验,只有data传参时,才能同时校验和序列化

class User(models.Model):name = models.CharField(max_length=16)code = models.CharField(max_length=20)class Meta:db_table = "users_organizations"managed = Falsefrom rest_framework import serializersclass userSerialize(serializers.Serializer):name = serializers.CharField(max_length=100)code = serializers.CharField(max_length=100)# 通常data是我们从请求中获取的数据,是我们要存入数据库的数据,所以我们需要对要存入数据库的数据进行校验
data = {'name':'zs','code':'11'}
user_serialize = userSerialize(data=data)

1. 调用 ser_data .is_valid()

1. userSerialize.is_valide() 继承于 BaseSerializer1. assert hasattr(self, 'initial_data'),如果没有 data参数没有传参,不允许调用 is_valid()函数2.self.initial_data  等于data,进入到  self.run_validationBaseSerializer(Field):def is_valid(self, *, raise_exception=False):# 如果没有 data参数没有传参,不允许调用 is_valid()函数assert hasattr(self, 'initial_data'), ('Cannot call `.is_valid()` as no `data=` keyword argument was ''passed when instantiating the serializer instance.')if not hasattr(self, '_validated_data'):try:self._validated_data = self.run_validation(self.initial_data)except ValidationError as exc:self._validated_data = {}self._errors = exc.detailelse:self._errors = {}if self._errors and raise_exception:raise ValidationError(self.errors)return not bool(self._errors)2. 进入到 Serializer.run_validation
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):def run_validation(self, data=empty):"""We override the default `run_validation`, because the validationperformed by validators and the `.validate()` method shouldbe coerced into an error dictionary with a 'non_fields_error' key."""(is_empty_value, data) = self.validate_empty_values(data)if is_empty_value:return datavalue = self.to_internal_value(data)try:self.run_validators(value)value = self.validate(value)assert value is not None, '.validate() should return the validated data'except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value3. 进入到 Field.validate_empty_values1.调用的是 字段的 validate_empty_values,调用 validate_empty_values时,self指的就是这个字段的实例化2. self.read_only 如果这个字段被设置的是只读字段,那们就不需要校验,直接返回是控制,只读字段是不需要传入数据存入到数据库的3. 如果data不为空,返回False 和 data
class Field:def validate_empty_values(self, data):"""Validate empty values, and either:* Raise `ValidationError`, indicating invalid data.* Raise `SkipField`, indicating that the field should be ignored.* Return (True, data), indicating an empty value that should bereturned without any further validation being applied.* Return (False, data), indicating a non-empty value, that shouldhave validation applied as normal."""if self.read_only:return (True, self.get_default())if data is empty:if getattr(self.root, 'partial', False):raise SkipField()if self.required:self.fail('required')return (True, self.get_default())if data is None:if not self.allow_null:self.fail('null')# Nullable `source='*'` fields should not be skipped when its named# field is given a null value. This is because `source='*'` means# the field is passed the entire object, which is not null.elif self.source == '*':return (False, None)return (True, None)return (False, data)4. 继续回到 Serializer.run_validationclass Serializer(BaseSerializer, metaclass=SerializerMetaclass):def run_validation(self, data=empty):"""We override the default `run_validation`, because the validationperformed by validators and the `.validate()` method shouldbe coerced into an error dictionary with a 'non_fields_error' key."""# 验证data不为空(is_empty_value, data) = self.validate_empty_values(data)if is_empty_value:return data# 来到 to_internal_valuevalue = self.to_internal_value(data)try:self.run_validators(value)value = self.validate(value)assert value is not None, '.validate() should return the validated data'except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value5. 来到 Serializer.to_internal_value1. if not isinstance(data, Mapping)  如果数据不是Mapping数据类型,则是无效的数据格式2. 来到 Serializer._writable_fields3. fields = self._writable_fields    fields是一个生成器
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):def to_internal_value(self, data):"""Dict of native values <- Dict of primitive datatypes."""if not isinstance(data, Mapping):message = self.error_messages['invalid'].format(datatype=type(data).__name__)raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='invalid')ret = OrderedDict()errors = OrderedDict()fields = self._writable_fieldsfor field in fields:validate_method = getattr(self, 'validate_' + field.field_name, None)primitive_value = field.get_value(data)try:validated_value = field.run_validation(primitive_value)if validate_method is not None:validated_value = validate_method(validated_value)except ValidationError as exc:errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)return ret6. 来到 Serializer._writable_fields1. 排除只读字段
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):@propertydef _writable_fields(self):for field in self.fields.values():if not field.read_only:yield field7. 来到 Serializer.fields1.返回一个 BindingDict容器2.容器中加入了对应的 字段名称 和 字段对应的 实例化类3.BindingDict 可以直接通过键取值,走的是 __getitem__ 魔术函数4. 对 BindingDict 进行迭代时 走的是  __iter__ 魔术函数
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):@cached_propertydef fields(self):"""A dictionary of {field_name: field_instance}."""# `fields` is evaluated lazily. We do this to ensure that we don't# have issues importing modules that use ModelSerializers as fields,# even if Django's app-loading stage has not yet run.# 在 instance 中传参已经写过相关部分fields = BindingDict(self)for key, value in self.get_fields().items():fields[key] = valuereturn fieldsclass BindingDict(MutableMapping):"""This dict-like object is used to store fields on a serializer.This ensures that whenever fields are added to the serializer we call`field.bind()` so that the `field_name` and `parent` attributescan be set correctly."""def __init__(self, serializer):self.serializer = serializerself.fields = OrderedDict()def __setitem__(self, key, field):self.fields[key] = fieldfield.bind(field_name=key, parent=self.serializer)def __getitem__(self, key):return self.fields[key]def __delitem__(self, key):del self.fields[key]def __iter__(self):return iter(self.fields)def __len__(self):return len(self.fields)def __repr__(self):return dict.__repr__(self.fields)8.  回到 Serializer.to_internal_valueclass Serializer(BaseSerializer, metaclass=SerializerMetaclass):def to_internal_value(self, data):"""Dict of native values <- Dict of primitive datatypes."""if not isinstance(data, Mapping):message = self.error_messages['invalid'].format(datatype=type(data).__name__)raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='invalid')ret = OrderedDict()errors = OrderedDict()# fields是一个生成器fields = self._writable_fieldsfor field in fields:# 看看自定义类中有哪些字段自定义了 validate_field_name的方法,获取自定义方法validate_method = getattr(self, 'validate_' + field.field_name, None)primitive_value = field.get_value(data)try:validated_value = field.run_validation(primitive_value)if validate_method is not None:validated_value = validate_method(validated_value)except ValidationError as exc:errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)return ret	9. Field.get_value()1.  html.is_html_input(dictionary)   dictionary是输入传入的data参数,如果是在html中输入的数据,则对输入的数据进行处理2. 不是html页面输入的数据,则直接取 对应fild_name对应的值,没有则返回empty  class Field:def get_value(self, dictionary):"""Given the *incoming* primitive data, return the value for this fieldthat should be validated and transformed to a native value."""if html.is_html_input(dictionary):# HTML forms will represent empty fields as '', and cannot# represent None or False values directly.if self.field_name not in dictionary:if getattr(self.root, 'partial', False):return emptyreturn self.default_empty_htmlret = dictionary[self.field_name]if ret == '' and self.allow_null:# If the field is blank, and null is a valid value then# determine if we should use null instead.return '' if getattr(self, 'allow_blank', False) else Noneelif ret == '' and not self.required:# If the field is blank, and emptiness is valid then# determine if we should use emptiness instead.return '' if getattr(self, 'allow_blank', False) else emptyreturn retreturn dictionary.get(self.field_name, empty)10. 回到  Serializer.to_internal_value:class Serializer(BaseSerializer, metaclass=SerializerMetaclass):def to_internal_value(self, data):"""Dict of native values <- Dict of primitive datatypes."""if not isinstance(data, Mapping):message = self.error_messages['invalid'].format(datatype=type(data).__name__)raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='invalid')ret = OrderedDict()errors = OrderedDict()# fields是一个生成器fields = self._writable_fieldsfor field in fields:# 看看自定义类中有哪些字段自定义了 validate_field_name的方法,获取自定义方法validate_method = getattr(self, 'validate_' + field.field_name, None)# 在data中根据 field.field_name取值,如果是空值则做相应的处理primitive_value = field.get_value(data)try:validated_value = field.run_validation(primitive_value)if validate_method is not None:validated_value = validate_method(validated_value)except ValidationError as exc:errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)return ret	11. 来到 Field.run_validation 1. 目标是对每个字段内的配置的校验规则进行验证
class Field:def run_validation(self, data=empty):"""Validate a simple representation and return the internal value.The provided data may be `empty` if no representation was includedin the input.May raise `SkipField` if the field should not be included in thevalidated data."""# 校验data是否为空,data是field 对应的字段值(is_empty_value, data) = self.validate_empty_values(data)if is_empty_value:return datavalue = self.to_internal_value(data)self.run_validators(value)return value12. 来到 Field.to_internal_value(value)
假设是 CharField1.将对应的值转换为字符串
class CharField(Field):def to_internal_value(self, data):# We're lenient with allowing basic numerics to be coerced into strings,# but other types should fail. Eg. unclear if booleans should represent as `true` or `True`,# and composites such as lists are likely user error.if isinstance(data, bool) or not isinstance(data, (str, int, float,)):self.fail('invalid')value = str(data)return value.strip() if self.trim_whitespace else value13. 回到 Field.run_validationclass Field:def run_validation(self, data=empty):"""Validate a simple representation and return the internal value.The provided data may be `empty` if no representation was includedin the input.May raise `SkipField` if the field should not be included in thevalidated data."""# 校验data是否为空,data是field 对应的字段值(is_empty_value, data) = self.validate_empty_values(data)if is_empty_value:return data# 如果对应的field字段Charfield,那么就是将值转换为字符串,将值进行序列化value = self.to_internal_value(data)self.run_validators(value)return value14. 来到 Field.run_validators()1. 如果报错,那么就会抛出错误
class Field:def run_validators(self, value):"""Test the given value against all the validators on the field,and either raise a `ValidationError` or simply return."""errors = []for validator in self.validators:try:if getattr(validator, 'requires_context', False):validator(value, self)else:validator(value)except ValidationError as exc:# If the validation error contains a mapping of fields to# errors then simply raise it immediately rather than# attempting to accumulate a list of errors.if isinstance(exc.detail, dict):raiseerrors.extend(exc.detail)except DjangoValidationError as exc:errors.extend(get_error_detail(exc))if errors:raise ValidationError(errors)15. 来到 Field.validators
如果kwargs中传入了 validators = ...,在调用   super().__init__(**kwargs) 时,会用 Field.__init__来初始化
如果传了validators,就用传入的validators,没有传则就用默认的validators,这个也要自己指明
class CharField(Field):def __init__(self, **kwargs):super().__init__(**kwargs)class Field:def __init__(self, *, read_only=False, write_only=False,required=None, default=empty, initial=empty, source=None,label=None, help_text=None, style=None,error_messages=None, validators=None, allow_null=False):if validators is not None:self.validators = list(validators)16. 回到 10	  Serializer.to_internal_value:class Serializer(BaseSerializer, metaclass=SerializerMetaclass):def to_internal_value(self, data):"""Dict of native values <- Dict of primitive datatypes."""if not isinstance(data, Mapping):message = self.error_messages['invalid'].format(datatype=type(data).__name__)raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code='invalid')ret = OrderedDict()errors = OrderedDict()# fields是一个生成器fields = self._writable_fieldsfor field in fields:# 看看自定义类中有哪些字段自定义了 validate_field_name的方法,获取自定义方法validate_method = getattr(self, 'validate_' + field.field_name, None)# 在data中根据 field.field_name取值,如果是空值则做相应的处理primitive_value = field.get_value(data)try:# 对field字段内配置的规则对值进行校验,字段内配置的规则通常是我们传参数传入进去的validated_value = field.run_validation(primitive_value)if validate_method is not None:# 自定义的序列化类中自定义的验证方法validated_value = validate_method(validated_value)except ValidationError as exc:errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:# 如果try中没有报错则走这一步,把字段名和字段值都更新到ret中set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)# return ret	17、  回到 4  Serializer.run_validationclass Serializer(BaseSerializer, metaclass=SerializerMetaclass):def run_validation(self, data=empty):"""We override the default `run_validation`, because the validationperformed by validators and the `.validate()` method shouldbe coerced into an error dictionary with a 'non_fields_error' key."""# 验证data不为空(is_empty_value, data) = self.validate_empty_values(data)if is_empty_value:return data# value是一个经过检验的字典,键是字段名,值是字段值value = self.to_internal_value(data)try:# 这个self指的是自定义的序列化类,因次我们可以在类属性中自定义序列化类 validatorsself.run_validators(value)# validate 继承于 Serializer,如果不重新定义validate,那么返回是自己本身的值value = self.validate(value)assert value is not None, '.validate() should return the validated data'except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value18、来到self.run_validators,run_validators 继承自Field,1、这个self指的是自定义的序列化类,因次我们可以在类属性中自定义序列化类 validatorsclass Field:def run_validators(self, value):"""Test the given value against all the validators on the field,and either raise a `ValidationError` or simply return."""errors = []for validator in self.validators:try:if getattr(validator, 'requires_context', False):validator(value, self)else:validator(value)except ValidationError as exc:# If the validation error contains a mapping of fields to# errors then simply raise it immediately rather than# attempting to accumulate a list of errors.if isinstance(exc.detail, dict):raiseerrors.extend(exc.detail)except DjangoValidationError as exc:errors.extend(get_error_detail(exc))if errors:raise ValidationError(errors)19class Serializer(BaseSerializer, metaclass=SerializerMetaclass):def validate(self, attrs):return attrs20、回到 1 BaseSerializer(Field):def is_valid(self, *, raise_exception=False):# 如果没有 data参数没有传参,不允许调用 is_valid()函数assert hasattr(self, 'initial_data'), ('Cannot call `.is_valid()` as no `data=` keyword argument was ''passed when instantiating the serializer instance.')if not hasattr(self, '_validated_data'):try:经过验证过的字典self._validated_data = self.run_validation(self.initial_data)except ValidationError as exc:self._validated_data = {}self._errors = exc.detailelse:如果不报错 self._errors 为空self._errors = {}if self._errors and raise_exception:raise ValidationError(self.errors)不报错,返回的就是Truereturn not bool(self._errors)

2、ser_data .is_valid() 验证总结

进入Serializer.run_validation,在run_validation中做了如下几件事
1. 首先获取字段的值
2. 先用字段内传入的validators进行校验
3. 检查每个字段是否写了 validate_字段名 方法,如果有那么对字段值进行校验
4. 如果自定义的序列化类中,类属性定义了validators,有validators对传入的字典值(包括所有字段的值)进行综合的校验
5. 如果自定义了validate,那么就用validate,对所有的字段值进行校验(传入的值是字典,包括所有的字段值)

3、验证完后,获取 ser_data .data,

class Serializer(BaseSerializer, metaclass=SerializerMetaclass):@propertydef data(self):# print('self测试。。。。',self)ret = super().data# print('ret测试。。。。',ret)return ReturnDict(ret, serializer=self)class BaseSerializer(Field):@propertydef data(self):print('base self....',self)print('base self....', self.__class__)if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):msg = ('When a serializer is passed a `data` keyword argument you ''must call `.is_valid()` before attempting to access the ''serialized `.data` representation.\n''You should either call `.is_valid()` first, ''or access `.initial_data` instead.')raise AssertionError(msg)if not hasattr(self, '_data'):if self.instance is not None and not getattr(self, '_errors', None):self._data = self.to_representation(self.instance)# 对validated_data进行序列化,之后的过程 跟instance传参一样的步骤elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):self._data = self.to_representation(self.validated_data)else:self._data = self.get_initial()return self._data

4、验证完后可以直接获取 validated_data ,因为校验之前,已经序列化过了,没有必要再调data了

在 is_valid()中第13步的时候,已经将值进行序列化了

class BaseSerializer(Field):@propertydef validated_data(self):if not hasattr(self, '_validated_data'):msg = 'You must call `.is_valid()` before accessing `.validated_data`.'raise AssertionError(msg)return self._validated_data

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com