Opened 16 years ago

Closed 12 years ago

Last modified 11 years ago

#9207 closed Bug (fixed)

Failing test code when using contenttypes app.

Reported by: Oliver Andrich Owned by: nobody
Component: contrib.contenttypes Version: 1.0
Severity: Normal Keywords:
Cc: oliver.andrich@…, aball@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In a project where I use the django.contrib.contenttypes app, I see errors in almost all my tests involving contenttypes. The error message below is from mysql, but I can also reproduce it for postgresql. sqlite3 seems to be save.

IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails 
(`test_test_content_type_sync_auth_bug/auth_permission`, CONSTRAINT `content_type_id_refs_id_728de91f` 
FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`))')

Seems as some created foreign key constraints aren't satisfied.

For reproduction I created a minimal django project (see the attached zip file). If you run "./manage.py test testapp" inside this project, you will see the error message.

I have tracked down this issue to the call to the flush command in the _pre_setup method of the django.test.TestCase class. Further tracking inside this method showed, that everything works fine until the django.contrib.auth apps post_syncdb signal handlers are called. The strange part about that is, that "./manager.py flush --verbosity=0 --noinput" basically does the same and doesn't cause such problems.

The model in the testapp application has a ForeignKey relationship to the ContentType model as described in http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/. The User model itself has no reverse generic relation is provided, as this is impossible for me with the User model.

I hope this information helps to track that issue, and I also hope I haven't missed anything.

Attachments (1)

test_content_type_sync_auth_bug.zip (9.0 KB ) - added by Oliver Andrich 16 years ago.
The minimal test project for this ticket.

Download all attachments as: .zip

Change History (18)

by Oliver Andrich, 16 years ago

The minimal test project for this ticket.

comment:1 by anonymous, 16 years ago

Component: UncategorizedContrib apps
Version: SVN1.0

comment:2 by Russell Keith-Magee, 16 years ago

Triage Stage: UnreviewedAccepted

Problem verified; test case works as reported.

It appears that the problem lies with content type caching. For some reason, the content type for the User model isn't being cleared from the cache (or, at least, is getting erroneously restored to the cache) somewhere between flushing the database and running the post_syncdb handler for the auth model.

comment:3 by Russell Keith-Magee, 16 years ago

Ok, I've got a workaround. If you replace:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'testapp'
)

with:

INSTALLED_APPS = (
    'django.contrib.contenttypes',
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'testapp'
)

i.e., make sure that contenttypes appears before auth in the INSTALLED APPS, the problem seems to resolve itself.

For those interested: flush removes the underlying contenttype objects, but the cache isn't flushed until the contenttypes post_syncdb handler is executed. The auth module accesses the cache, sees a stale object, and so doesn't create a new content type. When the auth module tries to save a permission against a stale cache object, the save fails.

comment:4 by Oliver Andrich, 16 years ago

The workaround works for me. Thanks.

comment:5 by Matt Grayson, 15 years ago

I'm getting the same kind of error, but not involving the auth module. Workaround does not work for me.

Tried stripping down the installed apps to just contenttypes and the single app using contenttypes.

When tests run I get errors like:

IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_libsite/ems_link`, 
CONSTRAINT `content_type_id_refs_id_47084aec` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`))')

in reply to:  5 ; comment:6 by Andrew Ball, 15 years ago

Cc: aball@… added

I'm seeing this also with MySQL and two custom apps installed with only the contenttypes app.

Replying to mattgrayson:

I'm getting the same kind of error, but not involving the auth module. Workaround does not work for me.

Tried stripping down the installed apps to just contenttypes and the single app using contenttypes.

When tests run I get errors like:

IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_libsite/ems_link`, 
CONSTRAINT `content_type_id_refs_id_47084aec` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`))')

in reply to:  6 comment:7 by Andrew Ball, 15 years ago

It turns out that what I was seeing seemed to be due to my running python manage.py sqlflush | python manage.py dbshell instead of python manage.py flush --noinput --verbosity=0 in unittests that I run via RPC to a running Django instance (not run by python manage.py test ). Using sqlflush instead of flush probably caused the post_syncdb hook for the contenttypes app to not get invoked, caching the contenttype cache to not be cleared. Things work fine if I use the flush command instead.

Replying to aball:

I'm seeing this also with MySQL and two custom apps installed with only the contenttypes app.

Replying to mattgrayson:

I'm getting the same kind of error, but not involving the auth module. Workaround does not work for me.

Tried stripping down the installed apps to just contenttypes and the single app using contenttypes.

When tests run I get errors like:

IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_libsite/ems_link`, 
CONSTRAINT `content_type_id_refs_id_47084aec` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`))')

comment:8 by Gabriel Hurley, 13 years ago

Component: Contrib appscontrib.contenttypes

comment:9 by Luke Plant, 13 years ago

Severity: Normal
Type: Bug

comment:10 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:11 by Aymeric Augustin, 12 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:12 by Claude Paroz, 12 years ago

Resolution: fixed
Status: newclosed

I was not able to reproduce this issue. Hopefully this doesn't happen any more in modern Django code.

comment:13 by anonymous, 11 years ago

We're running 1.4.1 and just hit this issue. however it was related to django permissions system. No idea why but swapping the order of 'django.contrib.auth' and 'django.contrib.contenttypes' in installed apps causes our test cases to pass.

With auth above contenttypes we get the following error.

IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (test_mixcloud.auth_permission, CONSTRAINT content_type_id_refs_id_728de91f FOREIGN KEY (content_type_id) REFERENCES django_content_type (id))')

The other way round, it works just fine.

comment:14 by Claude Paroz, 11 years ago

It would be nice to be able to indicate precisely how to reproduce the error. With the attached app, I wasn't able to reproduce this issue.

comment:15 by nicpottier@…, 11 years ago

I ran into this as well against Django 1.4.2 and MySQL using InnoDB. It seems very specific to machines.

I tracked it down a bit and the error for me is the same as in Comment 13, it is failing when trying to create the permissions for Auth because the content type for User wasn't yet created. This only occurs when running unit tests, and only against InnoDB.

Changing the order of content_type and auth in INSTALLED_APPS did fix the problem. The error itself does make sense, in that Signals aren't guaranteed to happen in order, and both Auth and ContentType are using them to do their work after models are synced. It seems like the workaround is not guaranteed to be reliable since there is no contract on signal call order.

comment:16 by Anssi Kääriäinen, 11 years ago

Hmmh. As an idea: would it be possible to call the permission creation from contenttype creation? You can't sync the permissions if contenttypes aren't installed.

Another solution is to turn off foreign key checks before the signals, then validate the db state afterwards. But this is likely going to be somewhat expensive to do...

comment:17 by Renato Alves, 11 years ago

Although marked as fixed it's not. Same problem is reported on #10827.

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