原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
【DRF配置管理】Django安装DRF框架并生成openapi风格文档
【DRF配置管理】如何实现JWT身份验证
【DRF配置管理】如何使用序列化:验证码、注册和登录
【DRF配置管理】如何结合ORM实现排序、模糊搜索、范围查询
【DRF配置管理】如何在视图类使用get_objects()
【DRF配置管理】如何实现RBAC页面菜单和按钮权限
【DRF配置管理】如何建立coreapi风格api接口文档
【DRF配置管理】如何建立swagger风格api接口文档
通常使用drf框架,都会使用序列化能力,尤其是ModelSerializer序列化。通过序列化我们可以实现字段的验证、文档的注释、异常获取等。
样例内容
class RegisterSerializer(ModelSerializer):
"""注册账户"""
password = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
code = serializers.IntegerField(write_only=True)
default_error_messages = {
"username_error": _('用户名必须以字母开头,且包含3~15个字母、数字'),
"username_registered_error": _('用户名已存在'),
'password_error': _('两次输入密码不一致'),
"phone_error": _('手机号格式有误,请重填'),
"phone_registered_error": _('手机号已注册'),
'code_error': _('验证码不正确'),
"email_error": _('电子邮箱格式有误,请重填'),
"email_registered_error": _('邮箱已注册'),
}
class Meta:
model = LoginUser
fields = ['username', 'phone', 'password', 'password2', 'code']
def validate_username(self, username):
"""单字段验证:名字"""
# 1.用户名格式
if not re.match(r'^[a-zA-z]\w{2,15}$', username):
raise serializers.ValidationError(self.error_messages['username_error'])
# 2.用户名是否存在
if LoginUser.objects.filter(username=username).exists():
raise serializers.ValidationError(self.error_messages['username_registered_error'])
return username
def validate_phone(self, phone):
"""单字段验证:手机号"""
# 1.验证手机号码是否合法
rs = r'^([+]?0?\d{2,3}-?|\([+]?0?\d{2,3}\)|\([+]?0?\d{2,3}\))?\d+$|^([+]?0?\d{2,3}-?|\([+]?0?\d{2,3}\)|\([+]?0?\d{2,3}\))?[1-9]\d{4,10}(-\d{1,10})?$'
if not re.match(r'1[0-9]\d{9}$', str(phone)) and not re.match(rs, str(phone)):
raise serializers.ValidationError(self.error_messages['phone_error'])
# 2.手机是否注册
if LoginUser.objects.filter(phone=str(phone)).exists():
raise serializers.ValidationError(self.error_messages['phone_registered_error'])
return phone
# def validate_code(self, code):
# """单字段验证:验证码"""
# phone =
# if cache.has_key(phone):
# old_code = cache.get(phone)
# print(str(code))
# print(1111)
# print(str(old_code))
# if str(old_code) != str(code):
# raise serializers.ValidationError(self.error_messages['code_error'])
def validate_email(self, email):
"""单字段验证:邮箱"""
# 1.邮箱格式
rs = '^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
if not re.match(rs, email):
raise serializers.ValidationError(self.error_messages['email_error'])
# 2.邮箱是否存在
if LoginUser.objects.filter(email=email).exists():
raise serializers.ValidationError(self.error_messages['email_registered_error'])
return email
def validate(self, attrs):
"""组合字段验证"""
password = attrs.get('password')
password2 = attrs.get('password2')
if password and password2 and password != password2:
raise serializers.ValidationError(self.error_messages['password_error'])
attrs['password'] = make_password(attrs['password2']) # 还可以通过重写create方法加密密码
# 验证码
phone = attrs.get('phone')
code = attrs.get('code')
if cache.has_key(phone):
old_code = cache.get(phone)
if str(old_code) != str(code):
raise serializers.ValidationError(self.error_messages['code_error'])
else:
raise serializers.ValidationError(self.error_messages['code_error'])
del attrs['password2']
del attrs['code']
return attrs
class RegisterSerializer(ModelSerializer):
"""注册账户"""
password = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
code = serializers.IntegerField(write_only=True)
class Meta:
model = LoginUser
fields = ['username', 'phone', 'password', 'password2', 'code']
使用serializers时,必须重写create和update方法
class BitableRecordsSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
def create(self, validated_data):
return True
def update(self, instance, validated_data):
instance.email = validated_data.get('email', instance.email)
instance.content = validated_data.get('content', instance.content)
instance.created = validated_data.get('created', instance.created)
return instance
default_error_messages = {
"username_error": _('用户名必须以字母开头,且包含3~15个字母、数字'),
"username_registered_error": _('用户名已存在'),
'password_error': _('两次输入密码不一致'),
"phone_error": _('手机号格式有误,请重填'),
"phone_registered_error": _('手机号已注册'),
'code_error': _('验证码不正确'),
"email_error": _('电子邮箱格式有误,请重填'),
"email_registered_error": _('邮箱已注册'),
}
class Meta:
model = LoginUser
fields = ['username', 'phone', 'password', 'password2', 'code']
read_only_fields = ['pic_id',]
# extra_kwargs = {'password': {'write_only': True}}
第一种:序列化字段验证
password = serializers.CharField(write_only=True)
第二种:单字段方法验证
def validate_email(self, email):
"""单字段验证:邮箱"""
# 1.邮箱格式
rs = '^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'
if not re.match(rs, email):
raise serializers.ValidationError(self.error_messages['email_error'])
# 2.邮箱是否存在
if LoginUser.objects.filter(email=email).exists():
raise serializers.ValidationError(self.error_messages['email_registered_error'])
return email
第三种:组合字段方法验证
def validate(self, attrs):
"""组合字段验证"""
password = attrs.get('password')
password2 = attrs.get('password2')
if password and password2 and password != password2:
raise serializers.ValidationError(self.error_messages['password_error'])
attrs['password'] = make_password(attrs['password2']) # 还可以通过重写create方法加密密码
# 验证码
phone = attrs.get('phone')
code = attrs.get('code')
if cache.has_key(phone):
old_code = cache.get(phone)
if str(old_code) != str(code):
raise serializers.ValidationError(self.error_messages['code_error'])
else:
raise serializers.ValidationError(self.error_messages['code_error'])
del attrs['password2']
del attrs['code']
return attrs