how customize User validator to accept whitespaces

Viewed 142

I want have custom validation for User to create name user with whitespaces in name. I do this like below but, I create User2 and change regex expression but it not changed validation conditions, it's not work. Have anybody idea why or how instead of I can do it?

models

from django.utils.translation import gettext_lazy as _

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


class MyUnicodeUsernameValidator(UnicodeUsernameValidator):
    print('test My')
    regex = r'^[\d]'
    message = _(
        'Enter a valid username. This value may contain only letters, '
        'numbers, and @/./+/-/_ characters.'
    )
    flags = 0


class User2(User):
    username_validator = MyUnicodeUsernameValidator()
    print(username_validator)

view

from django.shortcuts import render, get_object_or_404
from .models import User2
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import logout
from blog.models import Article




class MyUserCreationForm(UserCreationForm):
    class Meta:
        model = User2
        fields = ("username",)

def sign_up(request):
    context = {}

    form = MyUserCreationForm(request.POST or None)
    if request.method == "POST":
        if form.is_valid():
            form.save()
            return render(request, 'accounts/index.html')
    context['form'] = form
    return render(request,'registration/sign_up.html', context)
1 Answers

This approach will not work for several reasons. The first one is that you here make a subclass, which will be implemented as a sub-model: an extra model with no fields. But even if User was an abstract model, it would not work. The User model has a username field [GitHub] with a validator:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    # …
    username_validator = UnicodeUsernameValidator()

    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."),
        },
    )

but this is not as a "indirect reference" to the username_validator at the class level: a reference to the UnicodeUsernameValidator object, so even if you alter the validator, then that does not changes the fields already constructed.

I think the best way to implement this is Specifying a custom user model [Django-doc]. Making a user model that you will use as user model. You thus define a class:

from django.contrib.auth.base_user import AbstractBaseUser

class MyUser(AbstractBaseUser):
    username_validator = MyUnicodeUsernameValidator()
    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text='Some helptext that describes what are valid usernames',
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    # …

It will however require extra work (the steps specified in the documentation) to define the other fields, the manager, etc.

While you can do this, it might not be a good idea to allow spaces in the username. Usernames are sometimes used in URIs, and since whitespace is percentage encoded to %20, that will result in "ugly" URIs.

Related