#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)
Change History (18)
by , 16 years ago
Attachment: | test_content_type_sync_auth_bug.zip added |
---|
comment:1 by , 16 years ago
Component: | Uncategorized → Contrib apps |
---|---|
Version: | SVN → 1.0 |
comment:2 by , 16 years ago
Triage Stage: | Unreviewed → 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 by , 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.
follow-up: 6 comment:5 by , 16 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`))')
follow-up: 7 comment:6 by , 16 years ago
Cc: | 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 by , 16 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 , 14 years ago
Component: | Contrib apps → contrib.contenttypes |
---|
comment:9 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:12 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I was not able to reproduce this issue. Hopefully this doesn't happen any more in modern Django code.
comment:13 by , 12 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 , 12 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 , 12 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 , 12 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...
The minimal test project for this ticket.