DJango反序列化器的参数效验

Jerry 2020-06-01

ps:我是一名新手,代码基本靠抖,偶尔代码顺畅,只因运气帮忙。

两种定义序列化器的方式

#定义 serializers.py

class UserSerializer(serializers.ModelSerializer):
      """
      用户数据序列化器
      """
    class Meta:
        model = User
        #所有字段
        fields = "__all__"
        #选择个别字段
        #fields = (‘id‘, ‘name‘, ‘phone‘)


#序列化使用 view.py

query_set = User.objects.all()
serializer = UserSerializer(query_set, many=True)# 传入对象集时需指定many=True
serializer.data

#反序列化使用
通过data传入字段数据  通过is_valid方法校验参数合法性 save()保存入库
serializer = UserSerializer(data = data)
if serializer.is_valid():
      serializer.save

第二种反序列化方法

自定义验证行为:
1. validate_字段名:在序列化器中添加方法,方法名validate_字段名,参数为value,对value做校验,
raise serializers.ValidationError(‘XXXX‘),返回值value

2. validate:在序列化器中添加validate方法,可同时对多个字段进行验证

参数为attrs,从attrs中获取值,然后进行逻辑处理,抛出异常,返回值attrs

3.validator:在序列化器上方编写函数,参数value,对value校验,抛出异常

在序列化器字段中加入validator选项参数,为列表形式,值为函数名。

4.REST framework提供的validators:

UniqueValidator单字段唯一:字段中设置,参数为queryset

UniqueTogetherValidation联合唯一:class Meta中设置,参数queryset和fields

 

保存:如果验证成功,向基于validated_data完成数据对象的创建,可以通过create和update来实现

1.新建:在序列化器中重写create方法,参数为validate_data,

返回值为模型类.objects.create(**validated_data)

2.更新:在序列化器中重写update方法,参数instance即要更新的实例和validate_data

对validate_data字典获取其值,对无传递值给予默认值 instance.字段,并赋给instance.字段,然后调用instance.save()提交,返回值instance

注意点:
①实现了create和update方法后,在反序列化时既可以序列化对象.save()返回数据对象实例并保存或更新到数据库

②调用save时,如果有传instance实例,则调用update方法更新数据,否则调用create方法新建数据。

③调用save可传参,参数可从validated_data中获取

④如果没有传递所有required字段,会抛出验证异常,可通过使用partial=True实现部分字段更新

 
模型类序列化器ModelSerializer

可基于模型类自动生成一系列字段,会自动生成valiators和实现了默认的create和update方法

定义函数 validate_:对<field_name>字段进行验证

# 模型: models.py
 class User(models.Model):
     username = models.CharField(max_length=20)
     password = models.CharField(max_length=30)
      
       # 声明表名
    class Meta:
        db_table = "carousel"


 # 序列化器:serializer.py
class UserSerializer(serializers.Serializer):
    """用户个人数据序列化器"""

    #这里的字段设计要和model里面的一致
    username =serializers.CharField(max_length=20, write_only=True)
    def validate_name(self, value):
        # 校验部门名称
        if not re.match(‘^[\u4e00-\u9fa5]+$‘, value):
            raise ValidationError(‘部门名称只能为中文‘)
        return value

validate:同时对多个字段进行比较验证

# 模型: models.py
 class User(models.Model):
     username = models.CharField(max_length=20)
     password = models.CharField(max_length=30)

 # 序列化器: serializer.py
 class UserSerializer(serializers.Serializer):

     password = serializers.CharField(max_length=30, write_only=True)
     password2 = serializers.CharField(max_length=30, write_only=True)

     def validate(self, attrs):
         # 校验两次输入的密码是否正确
         password = attrs[‘password‘]
         password2 = attrs[‘password2‘]
         if password != password2:
             raise serializers.ValidationError(‘两次输入的密码不一样‘)
         return attrs

#这个时候视图密码的代码就剩了好多 view.py

from rest_framework.generics import CreateAPIView
from .myser import UserCreaterSerializers


class UserView(CreateAPIView):
    """注册用户"""
    # 指定用哪个序列化器
    serializer_class = UserCreaterSerializers

这是我写的一个的序列化操作

# 序列化
class UserCreaterSerializers(serializers.Serializer):
    # 用户id 只允许读
    id = serializers.IntegerField(read_only=True)
    """定义要传入的参数"""
    # 用户名
    username = serializers.CharField(
        min_length=2,
        max_length=20,
        error_messages={
            ‘min_length‘: ‘用户名太短‘,
            ‘max_length‘: ‘用户名太长‘
        }
    )
    password = serializers.CharField(
        write_only=True,
        min_length=6,
        max_length=20,
        error_messages={
            ‘min_length‘: ‘密码不能少于6个字符‘,
            ‘max_length‘: ‘密码不能超过20个字符‘
        }
    )
    password2 = serializers.CharField(
        write_only=True,
        min_length=6,
        max_length=20,
        error_messages={
            ‘min_length‘: ‘密码不能少于6个字符‘,
            ‘max_length‘: ‘密码不能超过20个字符‘
        }
    )
    phone = serializers.CharField(
        max_length=11,
        min_length=11,
        error_messages={
            ‘max_length‘: ‘输入的电话号码格式不对‘,
            ‘min_length‘: ‘输入的电话号码格式不对‘
        }

    )

    # 字段验证 验证用户名
    def validate_username(self, value):
        """
        对用户名进行合法检查
        :param value:要验证的用户名
        :return:如果验证通过返回value,否则抛出异常
        """
        # 用户名必须包含字母
        if not re.search(r‘[a-zA-Z\d_]‘, value):
            raise serializers.ValidationError(‘用户名中必须包含字母‘)
        # 验证用户名是否存在
        if User.objects.filter(username=value):
            raise serializers.ValidationError(‘用户名已存在‘)
        return value

    #验证手机号码
    def validate_phone(self, value):
        ‘‘‘
        验证手机号
        :param value: 要验证的手机号
        :return:如果手机号正确返回value,否则抛出异常
        ‘‘‘
        if re.search(r‘1[3567]\d{9}$‘, value):
            return value
        else:
            raise serializers.ValidationError(‘手机号码不符合规范‘)

    #多条数据验证,密码验证
    def validate(self, attrs):
        ‘‘‘
        验证两次输入的密码
        :param attrs: 同时对多个字段进行比较验证
        :return:如果密码比对正确返回attrs,也就是定义的哪一个密码,否则抛出异常
        ‘‘‘
        password = attrs[‘password‘]
        password2 = attrs[‘password2‘]
        if password != password2:
            raise serializers.ValidationError(‘两次输入的密码不一样‘)
        return attrs
      
    def create(self, data):
        """
        保存数据
        :param data: 一个包含用户名、密码等信息的字典
        :return: 返回一个user对象
        """
        user = User()
        user.username = data.get(‘username‘)
        user.phone = data.get(‘phone‘)
        user.password = data.get(‘password‘)

        user.save()
        return user

相关推荐