当前位置: 首页 > news >正文

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一个比 Nginx 还简单的 Web 服务器
  • SoM的理解
  • 头脑风暴中的颜色
  • [M二叉树] lc236. 二叉树的最近公共祖先(dfs+二叉搜索树)
  • IEEE P3233 标准启动会回顾:迈向去中心化存储标准化的第一步
  • 华为云CCE集群创建loadBalancer
  • 如何使用mcu 内置 flash 实现fatfs
  • jQuery基础——DOM
  • 要隐藏滚动条,您可以使用CSS中的overflow属性。
  • 编译可执行命令的FFmpeg
  • 达达熊搭建工程日志(持续更新中)
  • 【Python报错已解决】`ModuleNotFoundError: No module named ‘graphviz‘`
  • java利用JXL操作excel
  • 自然语言处理系列四十八》Word2vec词向量模型》算法原理
  • MyBatis 源码解析:SqlSessionFactoryBuilder 解析与实现
  • $translatePartialLoader加载失败及解决方式
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 2017-09-12 前端日报
  • Android交互
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • emacs初体验
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JS实现简单的MVC模式开发小游戏
  • leetcode讲解--894. All Possible Full Binary Trees
  • mysql 5.6 原生Online DDL解析
  • Node + FFmpeg 实现Canvas动画导出视频
  • PhantomJS 安装
  • React16时代,该用什么姿势写 React ?
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Wamp集成环境 添加PHP的新版本
  • 阿里云Kubernetes容器服务上体验Knative
  • 百度地图API标注+时间轴组件
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 猴子数据域名防封接口降低小说被封的风险
  • 欢迎参加第二届中国游戏开发者大会
  • 目录与文件属性:编写ls
  • 使用 Docker 部署 Spring Boot项目
  • 小而合理的前端理论:rscss和rsjs
  • ​插件化DPI在商用WIFI中的价值
  • ​如何使用QGIS制作三维建筑
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # 消息中间件 RocketMQ 高级功能和源码分析(七)
  • #git 撤消对文件的更改
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (02)Unity使用在线AI大模型(调用Python)
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (C)一些题4
  • (C语言)球球大作战
  • (分布式缓存)Redis持久化
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (文章复现)基于主从博弈的售电商多元零售套餐设计与多级市场购电策略
  • (转) RFS+AutoItLibrary测试web对话框