get_user_model in Django 1.7

2523 views
Skip to first unread message

Marcin Szamotulski

unread,
Jan 26, 2014, 6:39:42 AM1/26/14
to Django Developers
Hello,

I ask the question here since it is about the developed Django-1.7
version but if you think that I should ask it at django-users then
please excuse me.

When I use get_user_model in a top level of another app models I got an
error :

>>> django.setup()
File "<stdin>", line 1, in <module>
File "/home/coot/webapps/social_feel/venv/src/django/django/__init__.py", line 21, in setup
apps.populate(settings.INSTALLED_APPS)
File "/home/coot/webapps/social_feel/venv/src/django/django/apps/registry.py", line 105, in populate
app_config.import_models(all_models)
File "/home/coot/webapps/social_feel/venv/src/django/django/apps/base.py", line 180, in import_models
self.models_module = import_module(models_module_name)
File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/coot/webapps/social_feel/venv/src/django-registration/registration/models.py", line 15, in <module>
User = get_user_model()
File "/home/coot/webapps/social_feel/venv/src/django/django/contrib/auth/__init__.py", line 133, in get_user_model
user_model = apps.get_model(app_label, model_name)
File "/home/coot/webapps/social_feel/venv/src/django/django/apps/registry.py", line 182, in get_model
self.check_ready()
File "/home/coot/webapps/social_feel/venv/src/django/django/apps/registry.py", line 118, in check_ready
raise RuntimeError("App registry isn't ready yet.")


This because in Django 1.7 get_user_model is using apps.get_model which
checks if registry is ready, while the registry isn't, because it is
being built. So the question is how, in a reusable app get the
configured user model when the registry is not yet ready?

Cheers,
Marcin

Marcin Szamotulski

unread,
Jan 26, 2014, 6:44:24 AM1/26/14
to Django Developers
I found the answer in a very recent ticket:
https://code.djangoproject.com/ticket/21875

Cheers,
Marcin Szamotulski

Aymeric Augustin

unread,
Jan 26, 2014, 11:52:39 AM1/26/14
to django-d...@googlegroups.com
I wanted to write to the mailing list about this problem. Thanks for bringing it up.

Here’s what happens. Django 1.7 is more strict about the import sequence. Technically, the app registry population process isn't re-entrant anymore. As a consequence, it isn’t possible to call get_user_model() until the app registry is fully populated, that is, until all app packages and models modules have been imported.

A milder variant of this problem existed in Django 1.6. The docs recommend using settings.AUTH_USER_MODEL rather than get_user_model() as the target of ForeignKeys. In fact, you could get away with get_user_model(), but you started depending on the app registry population sequence, which wasn’t deterministic.

The most straightforward solution is to document under which conditions get_user_model() works. Technically, it works once all models modules have been imported. It can’t be used in models.py, but for example, it can be used in forms.py, assuming models.py doesn’t import forms.py.

I don’t know the implementation of custom user models very well. Can someone confirm whether this restriction is acceptable, or whether it makes get_user_model() useless?

An alternative is to have get_user_model() return a proxy object, but I really don’t like such hacks.

--
Aymeric.

Russell Keith-Magee

unread,
Jan 26, 2014, 7:49:18 PM1/26/14
to Django Developers
That restriction sounds entirely acceptable to me. get_user_model() is only required when you must have a reference to a specific model (e.g., for signals or forms); models allow string references to models which are resolved as part of the model loading process. If you can use a string-form reference to the User model, the call to get_user_model() isn't required. 

models.py may need to *import* get_user_model(), but it doesn't need to be invoked at the module level -- all the module level usages should be able to handle the string form. Individual methods on models might call get_user_model(), but at that point, the app registry will be populated.

I could even be convinced to put a safety mechanism into get_user_model() to cover this - since the app registry knows when it is fully populated, I can see a case for putting an "if not apps.is_populated(): raise Exception" in the implementation of get_user_model().

Yours,
Russ Magee %-)

Reply all
Reply to author
Forward
0 new messages