【问题标题】:How can I allow spaces in a Django username regex?如何在 Django 用户名正则表达式中允许空格?
【发布时间】:2017-02-10 13:21:23
【问题描述】:

我正在尝试允许在默认 django.contrib.auth.models 用户的用户名字段中接受空格,其他人之前曾直接或类似问题提出过:HereHereHere .我试图实施这些建议,但是我似乎找不到一个很好的例子来说明如何让它发挥作用。

据我了解,我需要更改用户名字段验证器中的正则表达式,为此我可以覆盖 contrib.auth.forms 中的 UserCreationForm 以实现用户名的不同字段并提供我自己的验证。 (如this 回答中所建议的那样)。

我具体怎么做?

作为参考,这是我目前用作注册表单的内容:

class SignUpForm(forms.ModelForm):
    """
    This form class is for creating a player
    """
    username = forms.CharField(label='Gamertag', max_length=16, widget=forms.TextInput(attrs={'placeholder': 'Gamertag', 'class': 'form-input'}))
    email = forms.EmailField(label='email', widget=forms.TextInput(attrs={'placeholder': 'Email', 'class': 'form-input', 'type':'email'}))
    password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'class': 'form-input'}))

    class Meta:
        model = User
        fields = ['username',
                  'email',
                  'password']
        widgets = {
            'password': forms.PasswordInput(),
        }

    def clean_email(self):
        email = self.cleaned_data.get('email')
        username = self.cleaned_data.get('username')
        if email and User.objects.filter(email=email).exclude(username=username).count():
            raise forms.ValidationError(u'A user with that email already exists.')
        return email

【问题讨论】:

  • 你运行的是哪个版本的 Django?
  • 我的Django版本是1.10.1

标签: python django django-models django-forms django-admin


【解决方案1】:

如果您不尝试修改默认 User 类上的字段,另一个 Jonathan 对 1.10 后的回答很好,除了几个小错误。

  • username_validator = MyValidator 必须是 username_validator = MyValidator() 否则验证器将静默失败并允许任何操作。
  • 破折号应该是括号中的最后一个字符或被转义(否则它将作为一个范围)。
  • 应使用空格而不是 \s 字符,这将允许任何空格(包括制表符和换行符)。

最终代码如下:

from django.contrib.auth.models import User
from django.contrib.auth.validators import UnicodeUsernameValidator

class MyValidator(UnicodeUsernameValidator):
    regex = r'^[\w.@+\- ]+$'

class MyUser(User):
    username_validator = MyValidator()

    class Meta:
        proxy = True  # If no new field is added.

(如果使用 Python 2,只需将 UnicodeUsernameValidator 替换为 ASCIIUsernameValidator)。请注意,点在括号内,因此不需要转义。

如果您正在修改 User 类中的字段,则可能是 AbstractUser 的子类化,并且您不能使用 proxy = True。这意味着AbstractUser 上的username 字段将使用AbstractUser 上声明的username_validator,而不是您的。要解决此问题,您几乎必须在模型上重新声明 username,如下所示:

from django.contrib.auth.models import AbstractUser
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils.translation import ugettext_lazy as _    

class MyValidator(UnicodeUsernameValidator):
    regex = r'^[\w.@+\- ]+$'

class MyUser(AbstractUser):
    username_validator = MyValidator()
    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
            error_messages={
            'unique': _("A user with that username already exists."),
        },
    )

确保您运行 makemigrations 并在之后进行迁移。

我已经尝试了多种方法在用户名被声明后更改验证器,但没有任何运气,所以看起来这是目前最好的方法。

【讨论】:

  • 请。将正则表达式更改为 r'^[\w\.@+\-\s]+$' 我不能因为愚蠢的规则,即编辑必须是 6 个字符或更多;)
  • 谢谢,我会用它重新测试一些东西。我愚蠢地只是复制了另一个答案而没有考虑正则表达式字符串。
【解决方案2】:

您需要修改验证器所在的用户。以下代码应该适用于 Django 1.9。

对于下面的这个用户,您应该能够在您编写的表单中使用MyUser 而不是User

from django.contrib.auth.models import AbstractUser
from django.core import validators

class MyUser(AbstractUser):
    validators=[
                validators.RegexValidator(
                    r'^[\w.@+-\s]+$',
                    _('Enter a valid username. This value may contain only '
                      'letters, numbers, spaces ' 'and @/./+/-/_ characters.')
                ),
            ],

    class Meta:
        proxy = True  # If no new field is added.

如果您想在 Django 1.10 中执行此操作,则必须稍微更改代码。在 Django 1.10 中添加了一个新属性username_validator,您必须覆盖它。您可以在manual 中阅读更多相关信息。

如果您使用 python2,则必须覆盖 ASCIIUsernameValidator,或者如果您使用 python3,则必须覆盖 UnicodeUsernameValidator。为简单起见,我假设您使用的是 python3。可以查看验证源代码here

from django.contrib.auth.models import User
from django.contrib.auth.validators import UnicodeUsernameValidator

class MyValidator(UnicodeUsernameValidator):
    regex = r'^[\w.@+-\s]+$'

class MyUser(User):
    username_validator = MyValidator

    class Meta:
        proxy = True  # If no new field is added.

【讨论】:

  • 非常感谢您的回复!不幸的是我的 Django 是 1.10 版本,它改变验证器的方法类似吗?
  • 我已将此代码放在 forms.py 和 models.py 中,但现在出现错误:TypeError: Abstract base class containing model fields not permitted for proxy model 'MyUser'.。我对 django 还很陌生,如果我做的事情明显错了,我很抱歉
  • 通过删除proxy = True 部分,我能够编译项目,但是我仍然无法注册用户名中有空格的用户。我将上面的代码复制到我的 forms.py 页面中,并将我的 signUpFrom 的“model = User”替换为“model = MyUser”,但它仍然不起作用。
  • 我的错,你能不能尝试继承 User 而不是 AbstractUser。以 proxy = True 开头。
  • 啊好的,现在可以使用代理=True 进行编译,我现在已经替换了它和 SignUpForm 元中的用户:class Meta: model = MyUser fields = ['username', 'email', 'password'] widgets = { 'password': forms.PasswordInput(), } 不幸的是,每当我尝试注册一个时,它似乎没有任何影响带有空格的用户名我仍然收到错误:“输入有效的用户名。此值可能仅包含英文字母、数字和 @/./+/-/_ 字符。”
猜你喜欢
  • 2020-12-07
  • 2012-10-09
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
相关资源
最近更新 更多