How to use 'User' as foreign key in Django 1.5
Asked Answered
S

2

50

I have made a custom profile model which looks like this:

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.ForeignKey('User', unique=True)
    name = models.CharField(max_length=30)
    occupation = models.CharField(max_length=50)
    city = models.CharField(max_length=30)
    province = models.CharField(max_length=50)
    sex = models.CharField(max_length=1)

But when I run manage.py syncdb, I get:

myapp.userprofile: 'user' has a relation with model User, which has either not been installed or is abstract.

I also tried:

from django.contrib.auth.models import BaseUserManager, AbstractUser

But it gives the same error. Where I'm wrong and how to fix this?

Sovereignty answered 17/10, 2013 at 17:44 Comment(3)
Is "django.contrib.auth" in INSTALLED_APPS in your settings.py ?Adamant
This one seem to work: 'user = models.OneToOneField(User, primary_key=True)'. However not sure what's difference.Sovereignty
The difference is that for a OneToOneField, a user can have only one profile (which is probably what you want).Sanfo
J
57

Change this:

user = models.ForeignKey('User', unique=True)

to this:

user = models.ForeignKey(User, unique=True)
Jesuitism answered 17/10, 2013 at 17:48 Comment(4)
Wouldn't it be more clear if we used OneToOneField instead of ForeignKey with unique constraint.Awakening
beware: If you do this and later on try to extend your User model creating a custom user model, you will need to change it to settings.AUTH_USER_MODEL as Anton Strogonoff said in his - more correct IMO - answerTransponder
Use OneToOneField if your relation is one to one, and add primary_key=TrueRechabite
For newer versions of Django, ForeignKey requires you to specify on_delete=models.CASCADE or another on_delete option.Pyrrhonism
P
62

Exactly in Django 1.5 the AUTH_USER_MODEL setting was introduced, allowing using a custom user model with auth system.

If you're writing an app that's intended to work with projects on Django 1.5 through 1.10 and later, this is the proper way to reference user model (which can now be different from django.contrib.auth.models.User):

class UserProfile(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
  • See docs for more details.

In case you're writing a reusable app supporting Django 1.4 as well, then you should probably determine what reference to use by checking Django version, perhaps like this:

import django
from django.conf import settings
from django.db import models


def get_user_model_fk_ref():
    if django.VERSION[:2] >= (1, 5):
        return settings.AUTH_USER_MODEL
    else:
        return 'auth.User'


class UserProfile(models.Model):
    user = models.ForeignKey(get_user_model_fk_ref())
Prolific answered 19/9, 2014 at 11:37 Comment(2)
I changed the code to note treat the version number as a decimal number. After all, the version 1.10 is considered higher than 1.5, which is not true if we treat them as decimal numbers.Phonography
@Phonography Looks good to me, didn’t like that dance with the decimals anyway. Tuple comparison beats it (maybe slightly less intuitive but it works!)Prolific
J
57

Change this:

user = models.ForeignKey('User', unique=True)

to this:

user = models.ForeignKey(User, unique=True)
Jesuitism answered 17/10, 2013 at 17:48 Comment(4)
Wouldn't it be more clear if we used OneToOneField instead of ForeignKey with unique constraint.Awakening
beware: If you do this and later on try to extend your User model creating a custom user model, you will need to change it to settings.AUTH_USER_MODEL as Anton Strogonoff said in his - more correct IMO - answerTransponder
Use OneToOneField if your relation is one to one, and add primary_key=TrueRechabite
For newer versions of Django, ForeignKey requires you to specify on_delete=models.CASCADE or another on_delete option.Pyrrhonism

© 2022 - 2024 — McMap. All rights reserved.