我刚刚开始使用Django REST Framework作为辅助项目,并且我试图将所有用户名都强制转换为小写字母(因为默认情况下它们区分大小写,并且我不希望人们使用{例如{1}}和kevin
。
这是我用来创建用户的代码:
Kevin
因此,用户可以通过向# The serializer
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
token = serializers.SerializerMethodField()
def create(self, validated_data):
user = get_user_model().objects.create(**validated_data)
user.set_password(validated_data['password'])
user.save()
return user
def get_token(self, user):
token = Token.objects.create(user=user)
return token.key
class Meta:
model = get_user_model()
fields = ('username', 'first_name', 'last_name', 'email', 'password', 'token')
# The View
class RegisterUserView(CreateAPIView):
model = User
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny, )
# And the URL pattern
urlpatterns = [
path(r'user/register/', RegisterUserView.as_view()),
]
发布至少一个用户名和密码来创建新帐户,然后在响应中,他将获得完整的用户对象(包括名字,姓氏,电子邮件和身份验证)令牌)。这行得通。
但是,我正在努力强制使用小写的用户名。例如,当我在序列化程序的create函数中添加类似user/register
之类的内容时,尝试创建具有相同用户名(但大小写不同)的用户时,服务器只会生成错误500“ UNIQUE约束失败:auth_user.username” )。那当然不是理想的,错误是500。
我发现了一些添加自定义用户管理器的建议,例如:
validated_data['username'] = validated_data['username'].lower()
但是在通过自定义用户类将其连接并添加到设置文件后,它也没有执行任何操作。我仍然可以使用用户名中的大写字母来创建用户。
最简单的解决方案是什么?
答案 0 :(得分:4)
如果您使用的是自定义用户模型,并且希望在整个Django中实施该模型,则可以创建一个自定义验证器。例如,创建一个validators.py
作为models.py
的兄弟姐妹,其中包含您的自定义用户模型:
from django.core import validators
from django.utils.deconstruct import deconstructible
from django.utils.translation import gettext_lazy as _
@deconstructible
class MyUsernameValidator(validators.RegexValidator):
"""
Validator for usernames.
- Only ASCII lowercase letters, numbers and underscore are supported.
- Must start with a letter.
"""
regex = r'^[a-z][a-z0-9_]+$'
message = _(
'Enter a valid username. This value may contain only lowercase ASCII letters, '
'numbers, and underscores. Must start with a letter.'
)
flags = 0
然后在您的自定义用户模型中,包括:
from .validators import MyUsernameValidator
...
class User(AbstractBaseUser, PermissionsMixin):
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = [
'first_name', 'last_name', 'email',
]
username = models.CharField(
max_length=16,
unique=True,
help_text=_(
'Required. 16 characters or fewer. Lowercase letters, digits _ only; must start with a letter.'
),
validators=[MyUsernameValidator()],
error_messages={
'unique': _("A user with that username already exists."),
},
)
有一些稍微简单的方法,但是只要您坚持使用ORM,它将通过Django强制执行。祝你好运!
答案 1 :(得分:1)
获得“唯一约束失败:auth_user.username”错误的原因可能是因为用户名验证是在未处理的用户名版本(即大写字母)上运行的,但是在插入时,您试图创建具有用户名的用户转换为小写。例如,假设您在数据库中有一个用户,其用户名如下:
my_username
然后,您尝试使用以下用户名创建用户:
My_Username
这将通过验证,因为数据库中没有用户名“ My_Username ”的用户,但是在创建时,您正在尝试创建用户名“ my_username ”的用户,它存在于数据库中,因此您遇到了IntegrityError。
有很多方法可以解决此问题,您可以在将用户名传递给序列化程序之前对其进行修改,因此在序列化程序上下文中,用户名始终为小写。您也可以像尝试过的那样使用自定义ModelManager,但是在保存之前,需要在管理器中将uesrname转换为小写。无论哪种方式,您都需要使用正确的用户名版本来验证数据,为此,您可以向序列化器添加验证,如下所示:
class UserSerializer(serializers.ModelSerializer):
...
validate_username(self, value):
try:
get_user_model().objects.get(username=value.lower())
except ObjectDoesNotExist:
# Good to go
pass
else:
# Username in use
raise serializers.ValidationError(...)
return value