17

I'm assuming that it is because my superuser depends on UserProfile which has no existing data yet. My model looks like

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

class UserProfile(models.Model):
    user = models.OneToOneField(User) # required
    location = models.CharField(max_length=100)
    age = models.PositiveIntegerField(blank=True,null=True)
    contribution_points = models.PositiveIntegerField()
    #acheivements = models.ManyToMany()

def create_user_profile(sender,instance,created,**kwargs):
    if created:
        UserProfile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)

However, I end up with the following error:

django.db.utils.DatabaseError: (1146, "Table 'savory_db.login_userprofile' doesn't exist")

despite having just ran syncdb

Does my model have any contradictory fields that would cause this error. Should UserProfile not be applied to the superuser? How should I prevent this?

the
  • 21,007
  • 11
  • 68
  • 101
user1431282
  • 6,535
  • 13
  • 51
  • 68
  • Did you add your UserProfile app to your settings? If not, the table won't be created with syncdb. Your code looks fine (at least at first glance-- I've implemented a very similar post-save method with no problems). – Colleen Dec 27 '12 at 18:43
  • 1
    Also, just to be clear, your statement "I'm assuming that it is because my superuser depends on UserProfile" is incorrect-- the dependency here goes the other way around. I would, in fact, be surprised if your createsuperuser command had completely failed-- I bet it created the superuser and just failed to create the associated profile. – Colleen Dec 27 '12 at 18:46
  • Also also, are you aware that in Django 1.5 the devs have allowed customization of the Django User model? If you instead extend the User model, you don't have to create a separate UserProfile (don't know if you actually intended for them to be separate, but just a thought) – Colleen Dec 27 '12 at 18:47
  • Thank you for clearing up my incorrect statement. I am currently running off of 1.4 but I am aware of the added customization. :) – user1431282 Dec 27 '12 at 19:47
  • So *did* you add UserProfile to your settings? – Colleen Dec 27 '12 at 19:48
  • yes, it was already there sorry for the hassle :< I realized that it was an issue with South. Definitely, thank you for the help. – user1431282 Dec 27 '12 at 19:49

2 Answers2

28

On Mar 23, 2011, at 4:25 AM, Malcolm Box wrote:

Further investigation: looks like it's a South/syncdb interaction. The UserProfile will be created by the south migration, but of course that hasn't run when the auth post_install runs to prompt for a superuser.

Sadly syncdb --migrate doesn't do the right thing either.

For now, I'm just creating a superuser manually using ./manage.py shell, but would welcome any ideas on how to solve this better.

Don't create the super user during syncdb, you user profile table will not exist. You must have a create signal on admin that creates a user profile, this looks like it is failing

The procedure you wan to use to initialize the database is:

python manage.py syncdb --noinput
python manage.py migrate
python manage.py createsuperuser

Reference : https://groups.google.com/forum/?fromgroups=#!topic/django-users/sBXllxrIdMc

Nicholas Murray
  • 13,305
  • 14
  • 65
  • 84
user1431282
  • 6,535
  • 13
  • 51
  • 68
  • 3
    For future reference, if you run `syncdb --all`, that should create tables even for things that are usually created via south. Additionally, if you're managing some things with south and some with syncdb, that would be a helpful thing to mention in your initial question :) – Colleen Dec 27 '12 at 19:57
1

I just ran into this very same issue - a profile model that is created through a migration, and a signal handler that breaks when the superuser is created using the initial syncdb.

My solution is as follows.

First of all, handle the case where the table doesn't exist yet. This is a bit ugly and perhaps too drastic (may mask other errors)

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    try:
        WheelProfile.objects.get_or_create(user=instance)
    except DatabaseError:
        logging.error("Failed to create profile for %s, perhaps migrations haven't run yet?" % instance)
        from django.db import connection
        connection._rollback()

Secondly, run a handler when migrations finish:

from south.signals import post_migrate

@receiver(post_migrate)
def create_profiles(app, **kwargs):
    if app == "wheelcms_axle":
        for u in User.objects.all():
            WheelProfile.objects.get_or_create(user=u)

This will of course also run when doing future migrations, creating profiles for users that don't have them. For me, that's not an issue.

Ivo van der Wijk
  • 16,341
  • 4
  • 43
  • 57