目前,在 django.contrib.auth 中,可以有两个用户名为“john”和“John”。我怎样才能防止这种情况发生。
最直接的方法是在 contib.auth.models 中添加一个干净的方法,并在保存之前将其转换为小写,但我不想编辑 contrib.auth 包。
谢谢。
目前,在 django.contrib.auth 中,可以有两个用户名为“john”和“John”。我怎样才能防止这种情况发生。
最直接的方法是在 contib.auth.models 中添加一个干净的方法,并在保存之前将其转换为小写,但我不想编辑 contrib.auth 包。
谢谢。
聆听模型,然后在那里进行检查pre_save
。Users
最少侵入性和最便携的方式。
这是一个关于它的外观示例(改编自用户配置文件示例):
def username_check(sender, instance, **kwargs):
if User.objects.filter(username=instance.username.lower()).count():
raise ValidationError('Duplicate username')
pre_save.connect(username_check, sender=User)
如果您使用 Postgres,则有更好的选择。Postgres 有一个不区分大小写的字段类型,citext
. 从 1.11 开始,Django 在django.contrib.postgres.fields.citext
. 您可能还需要处理 url 正则表达式中的大小写敏感问题。
将接受的答案更新为最新:
from django.db.models.signals import pre_save
from django.db.utils import IntegrityError
from django.dispatch import receiver
@receiver(pre_save, sender=User)
def username_check(instance, sender, **kwargs):
"""Ensure that username unique constraint is case insensitive"""
if sender.objects.filter(username__iexact=instance.username.lower()):
raise IntegrityError("Duplicate username")
我可能会使用用户名的自定义字段在模型上解决这个问题。
from django.db import models
class LowercaseCharField(models.CharField):
"""
Override CharField to convert to lowercase before saving.
"""
def to_python(self, value):
"""
Convert text to lowercase.
"""
value = super(LowercaseCharField, self).to_python(value)
# Value can be None so check that it's a string before lowercasing.
if isinstance(value, str):
return value.lower()
return value
然后在你的模型中..
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils.translation import gettext_lazy as _
# Assuming you saved the above in the same directory in a file called model_fields.py
from .model_fields import LowercaseCharField
class User(AbstractUser):
username = LowercaseCharField(
# Copying this from AbstractUser code
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[UnicodeUsernameValidator(),],
error_messages={
'unique': _("A user with that username already exists."),
},
)
# other stuff...
用户名将全部“自动”保存为小写字母。