This blog was first posted on my blog.
A few days ago, I was working on one of my old Django projects. It was running an old version of Django and I wanted to keep it updated with the latest changes of the framework.
So to check the admin site, I tried to create the superuser after connection to the local database.
python manage.py createsuperuser
When I passed a password similar to the username it failed saying, The password is too similar to the username.
This error triggered me to check the working behind this password validation feature.
The first thing that I looked into was the manage.py
file itself which in turn was importing and executing a method called, execute_from_command_line
.
I traced it back and found a package commands
containing everything that I wanted to know. This directory had two files.
1. createsuperuser.py
2. changepassword.py
The changepassword command
Since I had never used/ heard about the changepassword
command, I thought of trying it first and to my great pleasure, it worked. You have to pass the username as the first argument.
python manage.py changepassword username
Sometimes you find gold when you read the code, right? 😍
Now let's get back to the business and look into the createsuperuser
command class in more detail.
Fetching the correct database
If you have been using Django for some time, you would know that Django allows you to change a lot of things depending upon the settings you define.
This also includes using some random model as your base User model. This is the first thing that the superuser creation __init__
constructor method checks for.
Creating the superuser without interaction
You can use a version of the command that allows you to create the superuser without any interaction.
python manage.py createsuperuser --username ranvir --email abc@abc.com --no-input
Although the user created using this process will have no password. We can create the password either using the changepassword
command or the admin panel.
Required fields and interactive mode
For the default User
model, email
is the only required field but you can change that by changing your REQUIRED_FIELD
setting as well.
In the interactive mode( which is the default mode as well), the first thing that the prompt asks you to fill, is the username.
Django tries to smartly suggest the current system username as the default username. (Just Wow)
It won't suggest the system username if it is already taken. (That's AI for me 😂)
After the username, you have to fill in the required field which is the email field for the default User model.
Finally, you have to fill in the password field.
The validate password method
Sorry for keeping you waiting this long before jumping onto the real reason behind the post.
The validatepassword
is the function that is used to validate the password provided by the user.
Again, we can configure all these validators as well, if these different password validation doesn't work for you, go forward and remove the classes from your settings file.
These are the default validators.
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
If we use the default validators, then the password,
- Should not be similar to
username
,first_name
,last_name
andemail
. It also checks for the similarity using SequenceMatcher. It should be less than 0.7 similar which you can customize. (Told you, it's AI) - Should be greater than 8 characters.
- Should not be in the list of common passwords. The list of common passwords is in the file,
common-passwords.txt.gz
. It contains a list of around 20000 common passwords which you should not use. - Should not contain all numeric characters.
I would suggest keeping the basic configuration intact for the password handling. You can use your own validations on top of it as well.
So, that's it for this time. Till next time.
Top comments (0)