Opened 8 years ago

Closed 7 years ago

#25966 closed New feature (fixed)

Implement get_user_model() that can be used in models.py

Reported by: Marten Kenbeek Owned by: Markus Holtermann
Component: contrib.auth Version: dev
Severity: Normal Keywords:
Cc: rene@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

get_user_model() can only be used when the models for the user app have been loaded into the registry. This can be problematic when you need to subclass the user model, and you need the actual model in your own models.py file. If you want to support swappable models, your app must be after the user app in INSTALLED_APPS.

For reference, this use-case can be found in django-cms: https://github.com/divio/django-cms/blob/develop/cms/models/permissionmodels.py#L16

Lets implement an alternative to get_user_model() that can be used after the app registry is populated, but before the user model is loaded. This can work by actually importing the user model if it's not in the registry yet:

from importlib import import_module

from django.apps import apps
from django.conf import settings
from django.utils.module_loading import module_has_submodule

def get_user_model_safe():
    """
    Get the user model before it is loaded, but after the app registry is populated.
    """
    app_label, model_name = settings.AUTH_USER_MODEL.split('.')
    app_config = apps.get_app_config(app_label)
    models_module = import_module("%s.%s" % (app_config.name, "models"))
    return getattr(models_module, model_name)

Change History (10)

comment:1 by Tim Graham, 8 years ago

Triage Stage: UnreviewedAccepted

I think this is a duplicate of what's described in the comments of #22872, although the summary and component of that ticket need to be updated as I assume the original intent of updating the 1.7 release notes with the backwards-incompatibility won't be done at this point. I'm okay with closing either ticket as a duplicate.

comment:2 by Tim Graham, 7 years ago

Has patch: set

This is implemented as the last commit in PR #6547.

comment:3 by Tim Graham, 7 years ago

Patch needs improvement: set

I left comments for improvement on the PR.

comment:4 by Tim Graham, 7 years ago

Patch needs improvement: unset

comment:5 by Tim Graham, 7 years ago

Commits from the branch that precede this fix:

comment:6 by Tim Graham, 7 years ago

Patch needs improvement: set

comment:7 by Markus Holtermann, 7 years ago

Patch needs improvement: unset

I rebased Aymeric's PR onto current master and opened a new PR in https://github.com/django/django/pull/7550 .

comment:8 by Markus Holtermann, 7 years ago

Owner: changed from nobody to Markus Holtermann
Status: newassigned

comment:9 by Tim Graham, 7 years ago

Triage Stage: AcceptedReady for checkin

comment:10 by Markus Holtermann <info@…>, 7 years ago

Resolution: fixed
Status: assignedclosed

In cb7bbf97:

Fixed #25966 -- Made get_user_model() work at import time.

This makes it equivalent to: from django.contrib.auth.models import User.

Thanks Aymeric Augustin for the initial patch and Tim Graham for the
review.

Note: See TracTickets for help on using tickets.
Back to Top