How to customize username validation

Question:

I am trying to customize username validation for the django.contrib.auth User model. It says Usernames may contain alphanumeric, _, @, +, . and - characters. but I’d like to make it so that it would be invalid if the user made a username with @, ., -, +. How would I go about overriding this validation so when the user creates a username it is using my custom validation instead of the original UnicodeUsernameValidator?

I am using my own custom User model, but i’m inheriting from AbstractBaseUser Is there a simple way to add my username validation?

Asked By: Bytes

||

Answers:

There is a username_validator property that you can set on your model class:

Points to a validator instance used to validate usernames. Defaults to validators.UnicodeUsernameValidator.

To change the default username validator, you can subclass the User model and set this attribute to a different validator instance. For example, to use ASCII usernames:

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

class CustomUser(User):
    username_validator = ASCIIUsernameValidator()
Answered By: solarissmoke

@Bytes This is dirty trick but working:-

def loginup(request):
    if request.method == "POST":
        username = request.POST['username']
        password = request.POST['password']

        #Manual code to Check whether username is valid or not
        try:
         myuser = User.objects.get(username=username)
        except:
            myuser = False

        if myuser == False:
            mypass = False
        else:
            mypass = myuser.check_password(password)
        user = auth.authenticate(username=username, password=password)
        if myuser != False:
            if user is not None:
                auth.login(request, user)
                messages.success(request, "You have Successfully Logged in")
                return render(request, 'index.html')
            else:
                messages.error(request, "Invalid Password")
                return render(request, 'index.html')
        else:
            messages.error(request, "Invalid Username")
            return render(request, 'index.html')
    return render(request, 'index.html')
Answered By: Vivek Paliwar

Suppose you are working in your users app, and the name of your custom user model is CustomUser, which is inside users/models.py. If you don’t want to allow @, ., -, + in username, then create a forms.py, which will look like this:

users/forms.py

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = ('username', 'first_name', 'last_name', 'email')

    def clean(self):
        cleaned_data = super(CustomUserCreationForm, self).clean()
        username = cleaned_data.get('username')
        if ('@', '.', '-', '+') in username:
            self.add_error('username', 'Symbols @/./-/+ are not allowed in username.')
        return cleaned_data

# same for UserChangeForm
class CustomUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = CustomUser
        fields = ('username', 'first_name', 'last_name')
        # Removed email field. Anyone won't want to change email after registering. Go as you like.

    def clean(self):
        cleaned_data = super(CustomUserChangeForm, self).clean()
        username = cleaned_data.get('username')
        if ('@', '.', '-', '+') in username:
            self.add_error('username', 'Symbols @/./-/+ are not allowed in username.')
        return cleaned_data

Your custom error messages will be displayed if anyone tries to signup with @, ., -, + in username.

To change the Django default description Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only., your models.py should look like this:

users/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.validators import UnicodeUsernameValidator

User = get_user_model

class CustomUser(AbstractUser):
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        "Username",
        max_length = 150,
        unique = True,
        help_text = ("Required. 150 characters or fewer. Letters, and digits only."),
        # customize the above string as you want
        validators = [username_validator],
        error_messages = {
            'unique': ("A user with that username already exists."),
        },
    )
    email = models.EmailField(max_length=254, blank=False, unique = True)
    first_name = models.CharField(max_length = 30, blank = False)
    last_name = models.CharField(max_length = 50, blank = False)

And also don’t forget to check your views.py and your templates.

users/views.py

from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views.generic import CreateView
from .forms import CustomUserCreationForm
from .models import CustomUser
...

# Create your views here.
class SignUpView(SuccessMessageMixin, CreateView):
    form_class = CustomUserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'signup.html'
    success_message = 'Account was created successfully! Now Log In using your details.'
...

users/templates/signup.html

...

{% block content %}
    <h2>Sign Up</h2>    
    <div>
        <form action="" method="POST">
            {% csrf_token %}
            {{ form.as_p }}
            <button class="" type="submit">Sign Up</button>
        </form>
    </div>
{% endblock content %}
...

This was the minimum HTML you have to use. Then everything will work as you want.

You can add more customizations (such as adding Django crispy forms, or case insensitivity in username/email, or avoiding duplicates for users who sometimes types [email protected] and [email protected]. Both are the same emails. If you don’t include checks, then there will be duplicate users in your database.

Answered By: PhysicistSouravDas
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.