rest-framework数据校验

在使用rest_framework开发项目,后端都是提供api接口给前端,前端一般是用ajax提交数据给后端,对于前端提交过来的数据校验,就不能用django基础中介绍的使用form表单来校验.这个艰巨的任务就落在serializes身上,在rest_frameworkserializes有两个角色,分别为:

  • 1、序列号数据
  • 2、校验用户提交过来的数据,并提示错误信息

一、参考文档

二、简单基本的使用方式

  • 1、定义序列化的

    class GroupSerializer1(serializers.Serializer):
        # 定义title字段是必填字段及错误提示
        title = serializers.CharField(required=True, error_messages={'required': '必填字段'})
    
  • 2、在视图类中使用

    class GroupView(APIView):
        def get(self, request, *args, **kwargs):
            id = kwargs.get('id')
            obj = models.UserGroupModel.objects.filter(id=id).first()
            ser = GroupSerializer(instance=obj, many=False)
            res = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(res)
    
        def post(self, request, *args, **kwargs):
            # 配置就解析器才可以这样取值
            ser = GroupSerializer1(data=request.data)
            # 使用is_valid()函数来校验用户输入的数据
            if ser.is_valid():
                print(ser.validated_data)
            else:
                print(ser.errors)
            return HttpResponse('提交数据')
    

三、rest_framework使用函数自定义校验

  • 1、在serializes文件的类里面定义函数
  • 2、定义函数的格式

    def validate_字段名(self, 参数):
      pass
    
  • 3、自定义校验手机号码

    # 定义手机号码正则
    REGEX_MOBILE = "^1[3578]\d{9}$|^147\d{8}$|^176\d{8}$"
    
    import re
    from rest_framework import serializers
    from django.conf import settings
    
    from django.contrib.auth import get_user_model
    
    # 通过这种方式获取定义的用户模型(不管是定义什么类名都是这样获取)
    User = get_user_model()
    
    class UserSerializer(serializers.Serializer):
        # 自带的校验
        mobile = serializers.CharField(max_length=11, min_length=11, required=True,
                                       error_messages={'required': '手机号码必填', 'min_length': '手机号码长度错误',
                                                       'max_length': '手机号码长度错误'})
    
        def validate_mobile(self, mobile):
            """
            自定义手机号码校验
            :param mobile:
            :return:
            """
            if User.objects.filter(mobile=mobile).count():
                raise serializers.ValidationError('用户已经存在')
    
            if not re.match(settings.REGEX_MOBILE, mobile):
                raise serializers.ValidationError('手机号码格式错误')
    
            return mobile
    

四、在serializers中获取用户输入的信息

  • 1、直接使用self.initial_data["属性名"]来获取用户的输入
  • 2、在验证码中获取手机号码

    class UserSerializer(serializers.Serializer):
        """
        用户表的serializer
        """
        # 自带的校验
        mobile = serializers.CharField(max_length=11, min_length=11, required=True,
                                       error_messages={'required': '手机号码必填', 'min_length': '手机号码长度错误',
                                                       'max_length': '手机号码长度错误'})
        code = serializers.CharField(max_length=4, min_length=4, required=True,
                                     error_messages={'required': '验证码必填', 'min_length': '验证码长度错误',
                                                     'max_length': '验证码长度错误'})
    
        def validate_code(self, code):
            """
            自定义验证码的校验
            :param code:
            :return:
            """
            if VerifyCodeModel.objects.filter(mobile=self.initial_data.get('mobile')).count():
                pass
            else:
                raise serializers.ValidationError('验证码错误')
            return code
    

五、联合的validate(可以同时校验几个字段)的使用

  • 1、校验几个字段

      ....
      start = serializers.DateTimeField()
      finish = serializers.DateTimeField()
    
      def validate(self, attrs):
      # 传进来什么参数,就返回什么参数,一般情况下用attrs
          if data['start'] > data['finish']:
              raise serializers.ValidationError("finish must occur after start")
          return attrs
    
  • 2、修改字段

    class RegisterSerializer(serializers.ModelSerializer):
        """
        用户注册的序列化类
        """
        code = serializers.CharField(max_length=4, min_length=4, required=True,
                                     error_messages={'required': '验证码必填', 'min_length': '验证码长度错误',
                                                     'max_length': '验证码长度错误'})
        def validate_code(self, code):
            """
            自定义验证码的校验
            :param code:
            :return:
            """
            if VerifyCodeModel.objects.filter(mobile=self.initial_data.get('mobile')).count():
                pass
            else:
                raise serializers.ValidationError('验证码错误')
    
        def validate(self, attrs):
            attrs['mobile'] = attrs['username']
            del attrs['code']
            return attrs
    

六、定义类来校验

  • 1、官方提供的几个校验类

    • 1.UniqueValidator校验唯一
    • 2.UniqueTogetherValidator两个参数组合唯一的
    • 3.UniqueForDateValidator
    • 4.UniqueForMonthValidator
    • 5.UniqueForYearValidator
  • 2、自定义类来校验

      class TitleValidator(object):
              def __init__(self, base):
                      self.base = base
    
              def __call__(self, val):
                      if not val.startswith(self.base):
                              message = '必须要以{0}开头'.format(self.base)
                              raise serializers.ValidationError(message)
    

    ```py class GroupSerializer1(serializers.Serializer):

              title = serializers.CharField(required=True, error_messages={'required': '必填字段'},
                      # 使用自定义的类
                      validators=[TitleValidator(base=self.initial_data.get('title')), ])
    

七、其它知识的补充

  • 1、设置样式及设置字段显示的名字

      password = serializers.CharField(
              style={'input_type': 'password'}, label='密码', required=True, write_only=True
      )
    
  • 2、更多文档介绍传送门

八、使用案例(用户输入手机号码,获取验证码,然后注册)

  • 1、用户获取手机号码的验证

    # 引入缓存的包
    from django.core.cache import cache
    
    class SmsSerializer(serializers.Serializer):
        """
        用于用户发送手机验证码的serializer类
        """
        mobile = serializers.CharField(label='手机号码', max_length=11, min_length=11, required=True,
                                      error_messages={'required': '手机号码必填', 'min_length': '手机号码格式错误',
                                                      'max_length': '手机号码格式错误'})
    
        def validate_mobile(self, mobile):
            """
            验证手机号码的函数
            :param mobile:
            :return:
            """
    
            # 判断用户是否已经注册
            if User.objects.filter(mobile=mobile).count():
                raise serializers.ValidationError('该用户已经存在')
    
            # 正则判断手机号码格式
            if not re.match(settings.REGEX_MOBILE, mobile):
                raise serializers.ValidationError('手机号码格式错误')
    
            # 缓存中获取手机号码是否在20分钟内已经发送过短信的
            if cache.get(mobile):
                raise serializers.ValidationError('手机验证码已经发送,请查收短信')
    
            return mobile
    
  • 2、用户注册的验证

    class RegisterSerializer(serializers.ModelSerializer):
        """
        用户注册的序列化类
        write_only=True不会拿来序列化
        """
        code = serializers.CharField(max_length=4, min_length=4, required=True, label='验证码', write_only=True,
                                    error_messages={'required': '验证码必填', 'min_length': '验证码长度错误',
                                                    'max_length': '验证码长度错误'})
    
        username = serializers.CharField(required=True, allow_blank=False, label='用户名',
                                        validators=[UniqueValidator(queryset=User.objects.all())])
        password = serializers.CharField(
            style={'input_type': 'password'}, label='密码', required=True, write_only=True
        )
    
        def validate_code(self, code):
            """
            自定义验证码的校验(直接从缓存中取值)
            :param code:
            :return:
            """
    
            if cache.get(self.initial_data['username'], None) and cache.get(self.initial_data['username']) == code:
                pass
            else:
                raise serializers.ValidationError('验证码错误')
    
        def validate(self, attrs):
            attrs['mobile'] = attrs['username']
            del attrs['code']
            return attrs
    
        def create(self, validated_data):
            """
            重写创建方法
            :param validated_data:
            :return:
            """
            user = super(RegisterSerializer, self).create(validated_data=validated_data)
            user.set_password(validated_data['password'])
            user.save()
            return user
    
        class Meta(object):
            model = User
            fields = ['username', 'code', 'mobile', 'password']
    
  • 3、关于发送手机验证码的可以参考下一个章节的手机验证码

results matching ""

    No results matching ""