Custom User model fields
The default Django
User
model (i.e.
django.contrib.auth.models.User
class), uses a minimum
set of data fields, that include: username
,
email
, first_name
,
last_name
, date_joined
and
last_login
; in addition to the permission related
fields: password
, is_superuser
,
is_staff
and is_active
.
While these last fields are
enough for Django's built-in user functionality, they can fall
short if you're expecting to store additional user data (e.g. age,
telephone, address). There are two approaches to support additional
user data: create a separate model to store additional data and
create a user relationship to it (i.e. a User
with a
ForeignKey
) or override the default
django.contrib.auth.models.User
class to create a
custom user class.
Listing 10-14 illustrates the
first technique by creating an additional model to store extra user
data and creating a relationship to the
django.contrib.auth.models.User
class.
Listing 10-14. Model with extra user fields related to default Django user model
from django.contrib.auth.models import User from django.db import models class UserExtra(models.Model): user = models.ForeignKey(User) age = models.IntegerField(blank=True,null=True) telephone = models.CharField(max_length=15,blank=True,null=True)
The UserExtra
model
in listing 10-14 functions like any other model with a
ForeignKey
data type, and as such, has some
performance and maintenance implications when used in these
circumstances. On the negative side, the user data is distributed
in two database tables. One table for User
records and
another for UserExtra
records, which inevitably
requires two queries or a join query to obtain all data for a given
user -- see Chapter 7 for queries across model relationships. On
the positive side, this technique keeps a project's default Django
User
model class intact requiring no additional
configuration or development effort.
Next, let's take a look at the second technique which consists of creating a custom user class, a process that's illustrated in listing 10-15.
Listing 10-15. Custom User model to override default Django User model
# models.py (app registration)
from django.contrib.auth.models import AbstractUser from django.db import models class CoffeehouseUser(AbstractUser): age = models.IntegerField(blank=True,null=True) telephone = models.CharField(max_length=15,blank=True,null=True) # admin.py (app registration) from django.contrib import admin from .models import CoffeehouseUser class CoffeehouseUserAdmin(admin.ModelAdmin): pass admin.site.register(CoffeehouseUser, CoffeehouseUserAdmin) # settings.py AUTH_USER_MODEL = 'registration.CoffeehouseUser'
The first section in listing
10-15 shows the CoffeehouseUser
class to be used as
the custom user class. Notice the class inherits its behavior from
the AbstractUser
class which gives it the same fields
and behaviors as the default User
class (e.g.
username
, email
,etc.). Next, the
CoffeehouseUser
class declares the age
and telephone
fields using standard model fields,
giving the custom user class two more fields than the default
User
class.
Because the custom
CoffeehouseUser
class will override a project's
default User
class, this means the default
django.contrib.auth.models.User
class is no longer
used. Therefore, you must configure Django to use the custom
CoffeehouseUser
class anywhere user logic is
required.
The second section in listing
10-15 shows the Django admin configuration necessary to access the
new custom user class from the Django admin and be able to create,
read, update and delete users, just like it's done the the standard
django.contrib.auth.models.User
model class. Note the
next chapter covers Django admin configuration in greater
detail.
Finally, the third section in
listing 10-15 shows the Django settings.py
file with
the AUTH_USER_MODEL
set to
registration.CoffeehouseUser
, where
registration
represents the app name and
CoffeehouseUser
the custom user model. This last
configuration ensures user logic made throughout a project is made
on the CoffeehouseUser
model and not the default
User
model.
Once you run the migration operation with this custom user model class and configurations from listing 10-15, you'll see Django project users gain two additional fields.
Caution Custom user model implementations like the one in listing 10-15 should only be done at the outset of a project (i.e. one the first project migration).
Because a user model plays such a
central role in managing access to a Django project, you should not
attempt to implement custom user models like the one in listing
10-15 midway through a project. Doing so runs the risk of breaking
dependencies -- foreign keys -- used by other models to refer to
default django.contrib.auth.models.User
model records,
in addition, this also changes the underlying database table where
user data is stored. By implementing a custom user model at the
outset of a project, you guarantee any possible model dependencies
made on a user are done against custom user records and user data
is stored in a single database table from the outset.
In fact, if you plan to use a custom user model, but don't know which new fields to add at the outset, you can create a placeholder user model like the following:
class CoffeehouseUser(AbstractUser): pass
This snippet creates a model
identical to the default
django.contrib.auth.models.User
class, but lays the
groundwork to create user dependencies on the custom model, while
allowing the ability to add fields to the custom model as they're
needed with standard migrations like any other model.
Finally, another factor to take
into account when using a custom user model -- which isn't obvious
in listing 10-15 -- is how to reference a custom user model in
other places of a project. When you use the default
User
class, the statement from
django.contrib.auth.models import User
is commonplace in
models.py
and views.py
files to reference
a user, but with a custom model this reference is no longer
applicable.
To support custom user models,
Django offers the helper method get_user_model
that
returns a reference to whatever user model is defined in the
AUTH_USER_MODEL
variable in settings.py
.
In this manner, you can use the statement from
django.contrib.auth import get_user_model
to obtain a
reference to a project's user model from anywhere in a project. The
next section on authentication back-ends contains an example that uses the
get_user_model
method.