mom*_*aaa 13 django validation django-rest-framework
我正在尝试将django验证器 1.9与django rest框架序列化器集成.但序列化的"用户"(django rest框架)与django验证器不兼容.
这是serializers.py
import django.contrib.auth.password_validation as validators
from rest_framework import serializers
class RegisterUserSerializer(serializers.ModelSerializer):
password = serializers.CharField(style={'input_type': 'password'}, write_only=True)
class Meta:
model = User
fields = ('id', 'username', 'email, 'password')
def validate_password(self, data):
validators.validate_password(password=data, user=User)
return data
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
user.is_active = False
user.save()
return user
Run Code Online (Sandbox Code Playgroud)
我设法得到MinimumLengthValidator和NumericPasswordValidator正确,因为两个函数验证都不使用'user'进行验证.源代码在这里
摘自django源代码:
def validate(self, password, user=None):
if password.isdigit():
raise ValidationError(
_("This password is entirely numeric."),
code='password_entirely_numeric',
)
Run Code Online (Sandbox Code Playgroud)
对于像UserAttributeSimilarityValidator这样的其他验证器,该函数在验证中使用另一个参数'user'('user'是django用户模型,如果我没错的话)
摘自django源代码:
def validate(self, password, user=None):
if not user:
return
for attribute_name in self.user_attributes:
value = getattr(user, attribute_name, None)
Run Code Online (Sandbox Code Playgroud)
如何将序列化用户更改为django验证器(UserAttributeSimilarityValidator)可以看到的内容
摘自django源代码:
def validate(self, password, user=None):
if not user:
return
for attribute_name in self.user_attributes:
value = getattr(user, attribute_name, None)
if not value or not isinstance(value, string_types):
continue
Run Code Online (Sandbox Code Playgroud)
编辑
Django Rest Framework可以获得所有Django的内置密码验证(但它就像一个黑客).这是一个问题:
validationError就是这样的
[ValidationError(['此密码太短.它必须包含至少8个字符.']),ValidationError(['此密码完全是数字.'])]
验证不包含字段.Django休息框架将其视为
{
"non_field_errors": [
"This password is too short. It must contain at least 8 characters.",
"This password is entirely numeric."
]
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能注入一个字段 raise ValidationError
AKS*_*AKS 18
如您所述,当您使用验证器验证passwordin validate_password方法时UserAttributeSimilarityValidator,您没有该user对象.
我建议您不要进行字段级验证,而应通过在序列化程序上实现方法来执行对象级验证validate:
import sys
from django.core import exceptions
import django.contrib.auth.password_validation as validators
class RegisterUserSerializer(serializers.ModelSerializer):
# rest of the code
def validate(self, data):
# here data has all the fields which have validated values
# so we can create a User instance out of it
user = User(**data)
# get the password from the data
password = data.get('password')
errors = dict()
try:
# validate the password and catch the exception
validators.validate_password(password=password, user=User)
# the exception raised here is different than serializers.ValidationError
except exceptions.ValidationError as e:
errors['password'] = list(e.messages)
if errors:
raise serializers.ValidationError(errors)
return super(RegisterUserSerializer, self).validate(data)
Run Code Online (Sandbox Code Playgroud)
fap*_*aph 11
self.instance即使在进行字段级验证时,您也可以通过序列化程序对象访问用户对象.这样的事情应该有效:
from django.contrib.auth import password_validation
def validate_password(self, value):
password_validation.validate_password(value, self.instance)
return value
Run Code Online (Sandbox Code Playgroud)
使用序列化程序!有validate_fieldname办法!
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = (
'id', 'username', 'password', 'first_name', 'last_name', 'email'
)
extra_kwargs = {
'password': {'write_only': True},
'username': {'read_only': True}
}
def validate_password(self, value):
try:
validate_password(value)
except ValidationError as exc:
raise serializers.ValidationError(str(exc))
return value
def create(self, validated_data):
user = super().create(validated_data)
user.set_password(validated_data['password'])
user.is_active = False
user.save()
return user
def update(self, instance, validated_data):
user = super().update(instance, validated_data)
if 'password' in validated_data:
user.set_password(validated_data['password'])
user.save()
return user
Run Code Online (Sandbox Code Playgroud)