7

I'm working on a Django 1.5 project and I have a custom user model (let's call it CustomUser). Another app (SomeApp) needs to reference this custom user model. For the purposes of ForeignKey and such, the Django documentation says to use

User = settings.AUTH_USER_MODEL 

However, some functions in SomeApp.models need to access what would have formerly been known as User.objects. But User is now a string and not a class, so User.objects fails. The alternative would be

from django.contrib.auth import get_user_model
User = get_user_model()

Which works in other modules, but when I use this in models.py of SomeApp, Django raises an error:

ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)

Any ideas?

EDIT 1 - Traceback:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "...\django-badger\badger\__init__.py", line 7, in <module>
    from badger.models import Badge, Award, Progress
  File "...\django-badger\badger\models.py", line 26, in <module>
    User = get_user_model()
  File "...\lib\site-packages\django\contrib\auth\__init__.py", line 127, in get_user_model
    raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'MyApp.AuthUser' that has not been installed

EDIT 2 - INSTALLED_APPS settings:

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'south',
'MyApp',   # this is where my user model is defined
'SomeApp', # I try to use get_user_model() in this app's models.py; doesn't work.
'social_auth',
)
askvictor
  • 3,621
  • 4
  • 32
  • 45
  • Can you post full traceback ? – jpic Jul 04 '13 at 11:59
  • How did you define `AUTH_USER_MODEL` in your settings? In which application is the User and what is the class name for it? – matino Jul 04 '13 at 12:14
  • @matino - yes, it is defined in the settings. get_user_model() works fine in all other files except models.py. My custom user model AuthUser is defined in MyApp (in this example) – askvictor Jul 04 '13 at 12:22
  • Can we see your `INSTALLED_APPS` setting ? – jpic Jul 04 '13 at 12:29
  • Why use `get_user_model()` in the MyApp models.py instead of directly reffering with the class name? – matino Jul 04 '13 at 12:56
  • @matino - for defining fields, the class name works fine. The problem is when I need to access the objects (e.g. AuthUser.objects.all()) of the custom user model within SomeApp.models - it needs to have the actual class, not just its name. – askvictor Jul 05 '13 at 03:04
  • @jpic - Added. I've also tried moving MyApp to the top of this list of INSTALLED_APPS but that didn't make any difference. – askvictor Jul 05 '13 at 03:25

8 Answers8

11

I had the same problem just now and here is my 2 cents/solution.

If you want to use custom user model in models.py you'll be using for foreign keys settings.AUTH_USER_MODEL and for model methods you have to use get_user_model() but it has to be inside the method. It won't work outside because of circular import.

from django.conf import settings
from django.contrib.auth import get_user_model

class Event(models.Model):

    recipient = models.ForeignKey(settings.AUTH_USER_MODEL)
    ...

    def get_something(self):

        User = get_user_model()
        u = User.objects.get(id=...)
        ...
Freon
  • 111
  • 1
  • 2
10

Easy one, I think. I have had so many problems with recursive inclusions and so on... Well, the simplest thing to do, when you add a ForeignKey, is to write it like so:

user = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, on_delete=models.CASCADE, verbose_name=_(u"User"))

If you use get_user_model, do not use it like you do. Calling

User = get_user_model()

at the top of the module will try to import your User model, which may, indeed, not have been "installed". Instead, you have several choices:

  • At the top of your module, write

    User = get_user_model # then, you will have to use User() instead of User

  • Write get_user_model() everywhere it's useful. Always in methods or functions, never directly in a model module body.

Steve K
  • 10,879
  • 4
  • 39
  • 39
  • This worked for me. I was importing get_user_model() at the top of the file Makes complete sense. Thank you – Howie Jan 28 '14 at 16:29
  • How would you handle this problem in declaratory code? For example, a UserSerializer class has a Meta class where the model is specified. You can not defer the definition of the User model to execution time, since the whole definition is parsed during import time. – blueFast Dec 31 '15 at 14:55
3

Make sure your custom User model is not abstract.

Vladimir Prudnikov
  • 6,974
  • 4
  • 48
  • 57
1

I think this import from SomeApp makes a circular import. That's why there is a statement in docs to do something like ForeignKey with calling settings attribute.

As for me, I have encountered with this thing when I used django-filer app. There was a commit on github to prevent imports with get_user_model(). You can use the code there like an example to fix the problem.

This problem is very tricky, because when you try to call get_user_model() from shell - it would work.

Павел Тявин
  • 2,529
  • 4
  • 25
  • 32
1

The Django documentation has the answer: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.get_user_model

The most relevant section: Generally speaking, you should reference the User model with the AUTH_USER_MODEL setting in code that is executed at import time. get_user_model() only works once Django has imported all models.

The real solution is to make sure that you only use get_user_model() inside of a method, so that it won't get executed at import time.

Charl Botha
  • 4,373
  • 34
  • 53
0

You have to set,

AUTH_USER_MODEL = "yourapp.CustomUser"

in the settings.py. Then the get_user_model() will work. There is a clean documentation available.

Babu
  • 2,548
  • 3
  • 30
  • 47
  • It already is. get_user_model() works in other files except models.py. – askvictor Jul 04 '13 at 12:21
  • Check the order of your `INSTALLED_APPS`. The app which contains the `CustomUser` should be at top most than the other apps. Detailed explanation is here, https://code.djangoproject.com/ticket/19218 – Babu Jul 04 '13 at 12:30
0

I'm starting to think a workaround might be in order - any comments on the following in SomeApp/models.py:

from django.contrib.auth.models import User as UserModel
try:
    from django.contrib.auth import get_user_model
except ImportError:  #django <= 1.4 doesn't have get_user_model so define our own
    def get_user_model():
        return UserModel
User = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
...
def SomeModel(models.Model):
    user = models.ForeignKey(User)  # using the name of the model
    def some_method(self, email):
        qs = get_user_model().objects.filter(email=email)  # using function call to get model class 
askvictor
  • 3,621
  • 4
  • 32
  • 45
  • Hey @askvictor, how did you end up solving this? I'm having this same issue, but while running migrations, and on a package that is installed after my app. – tzenderman Nov 14 '13 at 11:28
  • @tzenderman - solved it by putting the project on hold while :-/ For migrations, I had some related issues which I solved by creating an intermediate migration along with needed_by or depends_on: http://stackoverflow.com/questions/17711515/django-south-circular-dependency – askvictor Nov 14 '13 at 21:26
0

Are you running South 0.8.3?

Ensure that you running South at least 0.8.4

GitHub issue South Release Notes

RedRory
  • 632
  • 1
  • 6
  • 18