Django Best Practices: Referencing the User Model
Tags: django, python, tutorial, beginners
Published: 2020-02-21 19:54:27

Django has a powerful, built-in [user authentication system](https://docs.djangoproject.com/en/dev/topics/auth/default/) that makes it quick and easy to add [login, logout, and signup functionality](https://learndjango.com/tutorials/django-login-and-logout-tutorial) to a website.

But how should a Django developer reference the User model? The [official Django docs](https://docs.djangoproject.com/en/dev/topics/auth/customizing/#referencing-the-user-model) list three separate ways:

* `User`
* `AUTH_USER_MODEL`
* `get_user_model()`

But I find the explanation given to be incomplete. So in this post we will review _why_ you might need to reference the User model and the pros/cons of each approach.

## Option 1: User
Let's assume we have a basic `models.py` file for a Blog. Here's what it might look like:

```python
# models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=50)
    body = models.TextField()
```

Now what if we wanted to add an `author` field so that we could track which user created a blog post and later add permissions on top of that?

The default way is to access `User` directly, which is the built-in Django model that provides us with `username`, `email`, `password`, `first_name`, and `last_name` fields.

```python
from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    body = models.TextField()
```

Pretty straightforward, no?

**The problem** is that we should always use a custom user model for new projects. The official docs [even say so](https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project).

But if we have a custom user model, we cannot refer to it as `User` so how do we reference it? It turns out there are two different ways.

## Option 2: AUTH_USER_MODEL
The first--and until recently best--way to reference the custom user model was via [AUTH_USER_MODEL](https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model).

To add a custom user to a new Django project you need to create a new user model and then set it as such in your `settings.py` file. I wrote a separate post on [how to do this](https://learndjango.com/tutorials/django-custom-user-model).

But the takeaway is that if we made a `users` app, a `CustomUser` model within it, then to override the default `User` model in our `settings.py` file we would do the following.

```python
# settings.py
AUTH_USER_MODEL = `users.CustomUser`
```

In our Blog `models.py` file the code would look like this:

```python
from django.conf import settings
from django.db import models

class Post(models.Model):
    author = models.ForeignKey(
      settings.AUTH_USER_MODEL,
      on_delete=models.CASCADE
    )
    title = models.CharField(max_length=50)
    body = models.TextField()
```

Using `settings` we pass the `AUTH_USER_MODEL` as a string into our model.


## Option 3: get_user_model
A third way to access the user model is via [get_user_model](https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.get_user_model). Up until the release of Django 1.11, `get_user_model` was not called at import time--meaning it would not always work correctly--however that has since been changed. It is therefore safe to use.

The code would look as follows:

```python
# settings.py
AUTH_USER_MODEL = `users.CustomUser`
```

Then in our Blog `models.py` file the code would look like this:

```python
from django.contrib.auth import get_user_model
from django.db import models

class Post(models.Model):
    author = models.ForeignKey(
      get_user_model(),
      on_delete=models.CASCADE
    )
    title = models.CharField(max_length=50)
    body = models.TextField()
```

`get_user_model()` will return the currently active user model: either a custom user model if specified or else `User`. It is therefore a cleaner approach, in my opinion, because `AUTH_USER_MODEL` **only** works if a custom user model is set.

## Conclusion
The takeaway is that working with User models is tricky in any web framework. Django has a robust user authentication system but given that many projects use a custom user model instead, the best approach when you want to refer to the current user model--of the three available--is to just always use `get_user_model`.