参数校验基本使用
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据,或保存成模型类对象。
-
序列化器的创建: 通过data传入字典数据
Serializer(instance=None, data=empty, **kwarg)
-
通过
is_valid
方法校验参数合法性is_valid()方法
:- 校验参数是否合法,校验通过返回True,否则返回False
- 传递参数:
is_valid(raise_exception=True)
- 验证失败时会抛出异常
serializers.ValidationError
- 响应时对应的状态码:400
- 验证失败时会抛出异常
errors属性
: 获取校验出错信息,字典类型。validated_data属性
: 校验通过得到的对象,类型为OrderedDict
-
案例
案例一:验证出错
my_dict = {'create_date':'2018'} serializer = DepartmentSerializer(data=my_dict) serializer.is_valid() # 验证不通过 # False serializer.errors # {'create_date': [ErrorDetail(string='Date has wrong format. # Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')], # 'name': [ErrorDetail(string='This field is required.', code='required')]}
案例二:验证通过
my_dict = {'name':'研发部33', 'create_date':'2018-1-1'}
serializer = DepartmentSerializer(data=my_dict)
serializer.is_valid() # 验证通过
# True
serializer.validated_data
# OrderedDict([('name', '研发部33'),
# ('create_date', datetime.date(2018, 1, 1))]
参数校验的几种方式
如果默认的字段类型和选项不能满足需求,需要再补充校验行为,可以使用以下三种方法:
- 通过字段中的
validators
选项进行校验 validate_<field_name>
方法:对<field_name>
字段进行验证validate
方法:对多个字段进行比较校验
一、通过 validators
选项校验
- 在序列化器字段中添加validators选项参数进行校验,例如:
def validate_name(value):
# 校验部门名称
if not re.match('^[\u4e00-\u9fa5]+$', value):
raise ValidationError('部门名称只能为中文')
return value
class DepartmentSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True, label='ID')
name = serializers.CharField(max_length=20, label='部门名称',
required=True, allow_null=True, validators=[validate_name])
...
二、validate_<field>
:对<field_name>
字段进行验证
- 注意:若校验失败,则
raise
ValidationError
异常
class DepartmentSerializer(serializers.Serializer):
"""部门数据序列化器"""
...
def validate_name(self, value):
# 校验部门名称
if not re.match('^[\u4e00-\u9fa5]+$', value):
raise ValidationError('部门名称只能为中文')
return value
测试
>>> from users.models import *
>>> from users.serializers import *
>>> s = DepartmentSerializer(data={'name':'研-发部22', 'create_date':'2018-1-1'})
>>> s.is_valid()
False
>>> s.errors
{'name': [ErrorDetail(string='部门名称只能为中文或英文字母', code='invalid')]}
三、validate:同时对多个字段进行比较验证
-
用户注册,校验两次输入的密码是否一致
# 模型: users/models.py class User(models.Model): name = models.CharField(verbose_name="用户名", max_length=20) password = models.CharField(verbose_name="密码", max_length=20) # 序列化器: users/serializer.py class UserSerializer(serializers.Serializer): name = serializers.CharField(max_length=20) password = serializers.CharField(max_length=20) password2 = serializers.CharField(max_length=20, write_only=True) # 新增用户时客户端传递请求参数: # {"name":"Jack", "password": "123456", "password2":"123456"} def validate(self, attrs): # 校验两次输入的密码是否正确 password = attrs['password'] password2 = attrs['password2'] if password != password2: raise serializers.ValidationError('两次输入的密码不一样') return attrs
-
测试
>>> from users.models import * >>> from users.serializers import * >>> s = UserSerializer(data={"name":"Jack", "password":"123456", "password2":"12345"}) >>> s.is_valid() False >>> s = UserSerializer(data={"name":"Jack", "password":"123456", "password2":"123456"}) >>> s.is_valid() True
保存或修改数据
-
Serializer
类的三个方法save()
方法: 保存数据create()
方法: 新增数据update()
方法: 修改数据
-
新增或修改数据
Serializer(instance=None, data=empty)
-
新增:创建序列化器时,没有传递了
instance
参数my_dict = {'name': '研发部xx', 'create_date': '2018-1-1'} s = DepartmentSerializer(data=my_dict) s.save() # 新增
-
修改:创建序列化器时,传递了
instance
参数department = Department.objects.get(id=1) my_dict = {'name': '研发部xx', 'create_date': '2018-1-1'} s = DepartmentSerializer(instance=department, data=my_dict) s.save() # 修改
-
部分修改:
partial=True
参数- 当修改数据时,序列化器默认要求传递所有
required=True
的字段,否则is_valid
验证不通过 -
可以通过设置
partial=True
允许只修改部分字段,如下:s = DepartmentSerializer(department, data={'create_date': '2017-1-1'}, partial=True)
- 当修改数据时,序列化器默认要求传递所有
-
-
案例:重写
Serializer
类的create()
和update()
方法
class DepartmentSerializer(serializers.Serializer):
"""部门序列化器"""
...
def create(self, validated_data):
"""保存部门"""
return Department.objects.create(**validated_data)
def update(self, instance, validated_data):
"""修改部门:instance为要修改的部门对象,
validated_data为用户发请求提交过来的数据,已经通过校验
"""
instance.name = validated_data.get('name', instance.name)
instance.create_date = validated_data.get('create_date', instance.create_date)
instance.save() # 修改数据库数据
return instance