The user authentication system provided by Django is extremely powerful and handles most of the authentication (Am I who I say I am?) and authorization (Am I authorized to do what I want to do?) needs of an web project. User accounts, groups and permissions, methods for handling passwords securely are part of this system.
Generally, this is adequate for most projects; however, there are situations where it becomes necessary to modify the behavior of a User or alter how their data is stored in the database. It should be noted that modifying the authorization and/or authentication process of a User will not be covered in this post.
For the people that prefers video content you can also watch me explaining the content of this post in the following video (but in Portuguese):
Extending with an extra Model
The simplest way to extend your User is to create a new model with a OneToOneField relation to the default User model. This model will contain all extra fields that extends your User.
If we are satisfied by the default of Django User model and just want to add extra fields (like a user profile), this is the easiest and simpler solution.
As an example, to create a user profile storing the date of birth and phone number of a User we could use the model:
|
|
However there are some caveats with this approach that we need to keep in mind to avoid unexpected issues such as:
- A new table is created, so retrieving data from both tables will
require more queries;
- The use of the select_related function can resolve performance issues caused by the new table. However, if we overlook this aspect, we may encounter unforeseen problems;
- A Profile instance is not created automatically when you create a new User.
We can solve this with a post_save signal handler;
- When multiple users are created simultaneously using the bulk_create method, post_save is not triggered, which may result in users being created without a Profile.
- We need to do some extra work if we want to have these fields added to the User details in Django Admin
To create a new Profile when a new User is created we need to catch post_save signal:
|
|
|
|
Running the application, we will ensure that every time we create a new User, a related Profile will be created as well:
|
|
As mentioned before, when creating instances in bulk, the signal will not be emited, so the Profile will not be automatically created:
|
|
One limitation of this approach is that we are not allowed to have required fields in the user profile without providing a default value.
As an example, if we require that date_of_birth is mandatory and
our Profile model is like the following:
|
|
When creating a new user, our post_save handler will fail:
|
|
Keeping in mind these caveats, extending the User model through this method is a simple and efficient solution that can meet the needs of many web applications.
If you want to start a discussion about this topic, you can send me an e-mail: [email protected] ✉️