Django using get_user_model vs settings.AUTH_USER_MODEL

PythonDjango

Python Problem Overview


Reading the Django Documentation:

get_user_model()

> Instead of referring to User directly, you should reference the user > model using django.contrib.auth.get_user_model(). This method will > return the currently active User model – the custom User model if one > is specified, or User otherwise. > > When you define a foreign key or many-to-many relations to the User > model, you should specify the custom model using the AUTH_USER_MODEL > setting.

I'm confused with the above text. Should I be doing this:

author = models.ForeignKey(settings.AUTH_USER_MODEL)

or this...

author = models.ForeignKey(get_user_model())

Both seem to work.

Python Solutions


Solution 1 - Python

Using settings.AUTH_USER_MODEL will delay the retrieval of the actual model class until all apps are loaded. get_user_model will attempt to retrieve the model class at the moment your app is imported the first time.

get_user_model cannot guarantee that the User model is already loaded into the app cache. It might work in your specific setup, but it is a hit-and-miss scenario. If you change some settings (e.g. the order of INSTALLED_APPS) it might very well break the import and you will have to spend additional time debugging.

settings.AUTH_USER_MODEL will pass a string as the foreign key model, and if the retrieval of the model class fails at the time this foreign key is imported, the retrieval will be delayed until all model classes are loaded into the cache.

Solution 2 - Python

New since Django 1.11.

Since Django 1.11 you can use get_user_model() in both cases! So if you don't want to bother about it further, just take it.

"in both cases" means: if you need the user model for accessing its attributes, as well as if you want to define a ForeignKey/ManyToMany-relation.

From the changelog:

> get_user_model() can now be called at import time, even in modules that define models.

so... is there still a reason to use settings.AUTH_USER_MODEL? Well, the docs still recommend the settings.AUTH_USER_MODEL (which is a string) for defining relations, but without giving an explicit reason. Might be beneficial for performance, but doesn't seem to matter much.

Code example:

from django.db import models
from django.contrib.auth import get_user_model
...
    ...
    user = models.ForeignKey(
        get_user_model(),
        null=True, # explicitly set null, since it's required in django 2.x. - otherwise migrations will be incompatible later!
        ...
    )

Solution 3 - Python

Since Django 1.11, get_user_model() actually uses settings.AUTH_USER_MODEL:

def get_user_model():
    """
    Return the User model that is active in this project.
    """
    try:
        return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
    except ValueError:
        raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
    except LookupError:
        raise ImproperlyConfigured(
            "AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
        )

Solution 4 - Python

settings.AUTH_USER_MODEL returns a string (the location of the User model) e.g. user_accounts.User.

get_user_model() returns the ACTUAL model class, not a string.

So in cases where you need the User model, use get_user_model(). If you need it's location (module.model as a string), use the settings.AUTH_USER_MODEL.

Solution 5 - Python

A way to fallback to the default user model if AUTH_USER_MODEL is not set:

from django.conf import settings
from django.contrib.auth.models import User

USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', User)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPrometheusView Question on Stackoverflow
Solution 1 - PythonknbkView Answer on Stackoverflow
Solution 2 - PythonIljaView Answer on Stackoverflow
Solution 3 - PythonMurey TasrocView Answer on Stackoverflow
Solution 4 - PythonImportErrorView Answer on Stackoverflow
Solution 5 - PythonsynwView Answer on Stackoverflow