Skip to content

Commit

Permalink
Use get_registered_model to load User model in Django 1.7
Browse files Browse the repository at this point in the history
In Django 1.7, get_user_model fails if the app cache isn't ready. As we
have to use it in many places in Oscar, this commit essentially loads
the User model like we load any other model in Oscar. This circumvents
the check for the model registry being ready.
Otherwise, there's major problems trying to avoid imports that trigger
the call to get_user_model (e.g. in forms and test factories) before the
first model is loaded (which then triggers Django's app load sequence).
  • Loading branch information
maiksprenger committed Aug 28, 2014
1 parent 80aa5a7 commit 37361b2
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions oscar/core/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,42 @@
from django.core.exceptions import ImproperlyConfigured


# A setting that can be used in foreign key declarations
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
# Two additional settings that are useful in South migrations when
# specifying the user model in the FakeORM
try:
AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit('.', 1)
except ValueError:
raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form"
" 'app_label.model_name'")


def get_user_model():
"""
Return the User model.
Return the User model. Does not require the app cache to be fully initialised.
This used to live in compat to support both Django 1.4's fixed User model
and custom user models introduced thereafter.
Support for Django 1.4 has since been dropped in Oscar, but our
get_user_model remains because code relies on us annotating the _meta class
with the additional fields, and other code might rely on it as well.
"""
model = django_get_user_model()

# As Oscar uses get_user_model all over the codebase, we need to be able to
# fetch the model without Django checking if the app cache is ready.
# Pre-Django 1.7, that check doesn't happen anyway and we can just use
# get_user_model. In Django 1.7, we revert to get_registered_model, which
# is the last remaining call to get into the model registry without
# Django enforcing that it's fully populated.
try:
from django.apps import apps
except ImportError:
# Django <1.7
model = django_get_user_model()
else:
# Django >=1.7
model = apps.get_registered_model(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME)

# Test if user model has any custom fields and add attributes to the _meta
# class
Expand All @@ -29,17 +54,6 @@ def get_user_model():
return model


# A setting that can be used in foreign key declarations
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
# Two additional settings that are useful in South migrations when
# specifying the user model in the FakeORM
try:
AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit('.', 1)
except ValueError:
raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form"
" 'app_label.model_name'")


def existing_user_fields(fields):
"""
Starting with Django 1.6, the User model can be overridden and it is no
Expand Down

0 comments on commit 37361b2

Please sign in to comment.