-
-
Notifications
You must be signed in to change notification settings - Fork 283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot delete or update a parent row: a foreign key constraint fails #34
Comments
Hi, can you tell me how to reproduce this issue? I've tried everything in the example project, and didn't get this issue. |
Hello, We have the same issue when deleting list of polymorphic elements. Here is the example
We are using postgresql and it seems that the delete statements generated during the delete will depend on the FIRST type found in the deleted list.
"sample_rating" elements are never deleted. Indeed, if we create a test, the result of If we create Rating first, then FreeText, it is the "sample_freetext" that is never delete... As soon as we have time, we will investigating the code, to see where ( and how ) the delete query set is "generate". |
Hum that is very strange. I will look as well. |
@dsaradini you mention writing a test for it - would you mind sharing it in a gist or as a PR? |
@chrisglass We're using the Pypi version 0.5.1. I will try with the trunk as soon as I have a moment, and also provide a running code that demonstrate the problem. |
We tracked down the error to a problem in the deletion collector of the Django ORM. The first problem is django/db/models/deletion.py:102. This method assumes that all objects in the list are the same model class (which is correct, if you use the normal Django manager). django-polymorphic is different. Therefore the code adds all objects with the first model class it finds in the list of objects. The objects which get passed to the add method are fetched in the related_objects method (line 240, same file). This method uses _base_manager of the related model (which is the base model of the multitable model construction). We fixed this bug by manually adding a _base_manager = models.Manager() to the PolymorhpicModel subclass, but this doesn't feel right. Another note: this only happens with foreignkeys/relations on the polymorphic base model. If you have foreignkeys in one of the submodels, everything works just fine. Hope the remarks help to find a clean solution for this issue. |
Thanks @stephrdev for the great help here. Can you post some example code (or gist) to demonstrate this issue? I'd love to fire up a project in the debugger to figure this out, but am keenly looking for model code. |
I also ran into this issue today, and it was caused by a
Again guys, please provide a usable example project. My situation can be completely different from yours, so I won't be able to track all edge-cases without an example project. |
I ran into the problem today. What is the status? |
I am also running into this problem, is the GenericRelation still a valid solution? The documentation of Django says this object is deprecated since 1.7 and will be completely removed in 1.9. |
The _base_manager = Manager() fix from @stephrdev worked for us too. Seems something in the PolymorphicModel's manager isn't quite right? |
mincn, can you elaborate more about that solution? so far I fixed the issue with a pre_delete signal in the Campaign class. I iterate over the relation and delete objects one at a time. I guess it's awful for performance, but at least it works. |
We have encountered this issue and chased it down to a bug in Django core's handling of reverse M2M relationships that target proxy models. In brief, the issue isn't specific to polymorphic but affects Django as well. It's probably just much more likely to occur if you use polymorphic. We have followed up in the relevant Django Track ticket: https://code.djangoproject.com/ticket/23076 Also created a new, more specific Django ticket: https://code.djangoproject.com/ticket/25520 |
Thanks a lot - that really helps! |
Because others continue to struggle with this I have created a gist of the (truly awful and hacky) work-around we are using for this issue, which monkey-patches Django's deletion collector to include proxy models: https://gist.github.com/jmurty/2034c24b6f91a3eaf51a I had intended to package this up more nicely in an installable project and include some related unit tests we have, but as always it's been hard to find the time. Please read the comments in that gist and use at your own risk. It works for us... for you, maybe not so much. |
I am also hitting this problem. The context I have seen it is when using the 'Delete selected' action in the admin. It only seems to happen if I try and bulk-delete objects of multiple polymorphic subclasses at once. I.e. if I have classes |
@mkjpryor-stfc We're seeing this same issue with the exact use-case that you described in your example. We're currently figuring out a workaround. |
To follow up on the monkey patch work-around I supplied earlier, the patch is now available in a more official location as part of our open-sourced ICEkit project. This approach has been working for us in production systems for months now, so while it is ugly it does work for us and it might help you too. There are monkey-patches for Django versions 1.8 and 1.7 starting in the code here: https://github.com/ic-labs/django-icekit/blob/0.16/icekit/publishing/monkey_patches.py#L76 The patch functions must be called to apply them, here's how we do it in an The patch should not be necessary in the latest versions of Django, so upgrading is probably the best option if you can, but in the meantime try the monkey-patches above. |
I'm still seeing this with Django 1.11. What is the recommended workaround at this time? I have re-opened the Django bug, because the previous "fix" didn't fix it (though may have fixed some other problems.) https://code.djangoproject.com/ticket/23076 |
Found an excellent workaround here #229 (comment) Seems to be a duplicate bug. |
Thanks for the pointer to that workaround @jstray and for following up on the Django issue. It's unfortunate the underlying problem isn't fixed in Django 1.11. I wasn't following along closely enough on the Django side to make sure it was really fixed. |
@jstray's workaround doesn't work for me with Django 1.11. |
This appears to also be broken in Django 2.0; I have been unable to find a workaround. |
Greetings from November 2019. This is still broken. |
Update: This fails: Basemodel.objects.all().delete() but this succeeds: for i in Basemodel.objects.all(): i.delete() Obviously it's not ideal, but it's a workaround until a fix is submitted. |
I think at this point you should search for alternative solutions. Introducing django-polymorphic as a dependency to your project is almost guaranteed to cause pain. This (and other breaking bugs) should be stated upfront in the readme file. I think most people come here and are given the impression that everything is working fine and smooth. I'm not saying this is a bad project, but as long as it's not part of core Django it's very likely to encounter such breaking bugs that will not be fixed anytime soon. |
Base.objects.all().non_polymorphic().delete() also works well. |
I have to agree with @bogdanpetrea, given this bug hasn't yet been addressed in Django core, and is likely to manifest when using django-polymorphic (I lost a few hours on a project today encountering and resolving this very issue), could it be noted somewhere in the docs? |
i had the same problem deleting the parent model i was using the generic Delete view then |
Well its 2021. How late can they get man |
In 2022 the problem still occurs, in Django 4.0.1 and Django-polymorphic 3.1.0. In my case, the following workaround (denisorehovsky/django-rest-polymorphic#29 (comment)) seems to be good: class Parent(PolymorphicModel):
non_polymorphic = models.Manager()
class Meta():
base_manager_name = 'non_polymorphic' This problem should really be fixed, or at least documented... |
PRs welcome! Be the change you want to see in the world. |
In 2022, the solution I used is still this one. It's quite bad for performance but since I expect to almost never use delete in production, it will do the job. Let's prey for a fix someday in the future. |
Any fix for this? |
unsubscribe
…On Wed, Jan 11, 2023 at 11:10 AM Philipp ***@***.***> wrote:
@pfcodes <https://github.com/pfcodes> There are some suggestion in #229
<#229>
—
Reply to this email directly, view it on GitHub
<#34 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAS7I64ORCFLCYL7R4HDCTWR3LN7ANCNFSM4AE2JOQA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
The root of the issue is that Django doesn't expect models to be automatically polymorphic during deletion and this messes up the order of the deletions leading to constraint errors. I've implemented a workaround on my project by first including the library source code to my repo so I could change it then I added a static global_polymorphic_disabled = 0 to the PolymorphicQuerySet class and in PolymorphicModelIterable.__iter__ I altered the if to take into account global_polymorphic_disabled:
Then I changed my base model classes to disable auto polymorphism for all deletions. I had to set global_polymorphic_disabled even for non polymorphic models to avoid the foreign key error.
|
Using the delete_selected admin action can cause an error similar to the following:
IntegrityError: (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (
foo2
.bar
, CONSTRAINTformat_ptr_id_refs_id_270cb9d612063f8e
FOREIGN KEY (format_ptr_id
) REFERENCESfoo1
(id
))')The text was updated successfully, but these errors were encountered: