如何在Django用户名正则表达式中允许空格?

时间:2016-10-02 13:09:33

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

我正在尝试允许空格被接受到默认django.contrib.auth.models用户的用户名字段中,其他人在此之前直接或类似问题:HereHere,和Here。我试图实现这些建议但是我似乎无法找到一个如何使其工作的好例子。

根据我的理解,我需要更改用户名字段验证器中的正则表达式,为此我可以覆盖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

2 个答案:

答案 0 :(得分:1)

如果您没有尝试修改默认用户类中的字段,那么除了几个小错误之外,其他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。这意味着username上的AbstractUser字段将使用username_validator上声明的AbstractUser,而非您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."), }, ) ,如下所示:

{{1}}

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

我已尝试过多种方法在用户名已经宣布后更改用户名上的验证器,但是没有运气,所以看起来这是目前最好的方法。

答案 1 :(得分:0)

您需要修改验证程序所在的用户。以下代码适用于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.