Opened 7 years ago

Closed 3 years ago

Last modified 2 years ago

#9207 closed Bug (fixed)

Failing test code when using contenttypes app.

Reported by: oliverandrich 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 oliverandrich 7 years ago.
The minimal test project for this ticket.

Download all attachments as: .zip

Change History (18)

Changed 7 years ago by oliverandrich

The minimal test project for this ticket.

comment:1 Changed 7 years ago by anonymous

  • Component changed from Uncategorized to Contrib apps
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Version changed from SVN to 1.0

comment:2 Changed 7 years ago by russellm

  • Triage Stage changed from Unreviewed to Accepted

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 Changed 7 years ago by russellm

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 Changed 7 years ago by oliverandrich

The workaround works for me. Thanks.

comment:5 follow-up: Changed 7 years ago by 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:6 in reply to: ↑ 5 ; follow-up: Changed 7 years ago by aball

  • 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`))')

comment:7 in reply to: ↑ 6 Changed 7 years ago by aball

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 Changed 4 years ago by gabrielhurley

  • Component changed from Contrib apps to contrib.contenttypes

comment:9 Changed 4 years ago by lukeplant

  • Severity set to Normal
  • Type set to Bug

comment:10 Changed 4 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:11 Changed 4 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:12 Changed 3 years ago by claudep

  • Resolution set to fixed
  • Status changed from new to closed

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

comment:13 Changed 3 years ago by anonymous

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 Changed 3 years ago by claudep

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 Changed 3 years ago by nicpottier@…

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 Changed 3 years ago by akaariai

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 Changed 2 years ago by rjalves

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

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