rest-framework数据校验
在使用rest_framework
开发项目,后端都是提供api
接口给前端,前端一般是用ajax
提交数据给后端,对于前端提交过来的数据校验,就不能用django
基础中介绍的使用form
表单来校验.这个艰巨的任务就落在serializes
身上,在rest_framework
中serializes
有两个角色,分别为:
- 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
- 1.
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、关于发送手机验证码的可以参考下一个章节的手机验证码