Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: IntegrityError: column user_id is not unique

Tags:

python

django

I wanted to test something that uses a User objects.

But for some reason I am getting:

IntegrityError: column user_id is not unique

I've been banging my head against the wall for a while now and it seems I can't figure out what is wrong. At first I thought that maybe the database isn't getting flushed in between tests but I traced User.objects.all() and it's an empty list.

This is the test:

from django.contrib.auth.models import User
from django.test import TestCase

class TestSomething(TestCase):
    def test_create_user(self):
        User.objects.create_user('foo', 'foo@bar', 'bar')

My test settings:

from settings import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', 
        'NAME': ':memory:',
    }
}

TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

Update:

I should read my strack traces a little better. It's actually the following signal that is causing the problem.

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile(user=instance).save()
like image 900
Pickels Avatar asked Jun 17 '11 15:06

Pickels


2 Answers

I worked around the problem by adjusting my signal like this:

from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.get_or_create(user=instance)

This solved the symptom but not really the cause. I think that mixing normal tests with Django tests is causing an error somewhere. When I ran the test in my question alone it would work.

If I get no other answers I'll mark this one as correct.

like image 50
Pickels Avatar answered Sep 24 '22 00:09

Pickels


I ran into the same problem and there's a simple fix. The problem happens if you run 'manage.py dumpdata' and you already have a UserProfile in your database. The UserProfile will be in the json file, so when you load the test data fixture and try to create a new UserProfile with the same username in your test, you will get a conflict since a UserProfile with that User already exists. The solution is to just delete the UserProfile from the json fixture.

So, as an example:

  • You have an existing database with User with the username 'mathew' and a UserProfile tied that User
  • You run manage.py dumpdata
  • Now the resulting json fixture has the UserProfile in it, because it is part of your app's models (but not the User)
  • Now you try to create a user in your test like this: 'User.objects.create_user('mathew', '[email protected]', 'password')'
  • Your post save signal will trigger and try to create a UserProfile associated to User 'mathew'
  • But that UserProfile already exists and so you get an error

Hope that helps.

like image 33
mathew Avatar answered Sep 24 '22 00:09

mathew