-
Notifications
You must be signed in to change notification settings - Fork 230
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
get
operation raises DoesNotExist
raised when related FK with on_delete=SET_NULL
is deleted
#348
Comments
Here's an implementation: def invalidate_on_delete_set_null_relations_pre_delete(sender, instance, **kwargs):
"""
Discover related objects that have an FK with `on_delete=SET_NULL` that points to
an object being deleted. Add a list of these related objects to the instance for
later invalidation in a `post_delete` signal handler.
We need to execute the query and save a list of objects here, because the FK fields
will already be set null in `post_delete`.
"""
objs = []
for ro in type(instance)._meta.get_all_related_objects():
if ro.field.rel.on_delete == models.SET_NULL:
objs.extend(ro.model.objects.filter(**{ro.field.name: instance.pk}))
instance._invalidate_on_delete_set_null_related_objs = objs
pre_delete.connect(invalidate_on_delete_set_null_relations_pre_delete)
def invalidate_on_delete_set_null_relations_post_delete(sender, instance, **kwargs):
"""
Invalidate related objects that have an FK with `on_delete=SET_NULL` that points to
an object being deleted, stored on the instance by a `pre_delete` signal handler.
"""
from cacheops import invalidate_obj
for obj in instance._invalidate_on_delete_set_null_related_objs:
invalidate_obj(obj)
post_delete.connect(invalidate_on_delete_set_null_relations_post_delete) Is there a better way to bulk invalidate than fetching all related instances into a big list and calling |
I think cacheops may simply invalidate user here, it will be refetched from db with field set null. Can you create a test for it? There is an instruction at the end of README. |
I ran into this same issue but in a slightly different context. I was able to solve it by adding the FK relation to a prefetch_related() clause which causes the invalidation logic to properly link that relation and invalidate it. So while my exact case if different than the one referenced here, I assume this would still work:
|
Oops. Didn't mean to close this. |
Will anyone be willing to write a test for this? The instruction is at the end of the README. |
I have the same problem with this case def test_delete_1(self):
category = Category.objects.create()
Post.objects.create(category=category)
Post.objects.create(category=category)
objs = Post.objects.all().only("pk", "title").select_for_update()
# ...
# Some logic here for create, update and then delete models
# ...
objs.filter(pk__in=Post.objects.all().values("pk")).delete() Trace
PR #371 |
As far as I see @voron3x issue is different from the original one. They doesn't seem to be connected. |
I got the same problem, created PR #406 to reproduce the bug
|
Task and Job models have many to one relationship with User model on assignee and reviewer fields. And on deleting the parent model, these fields are set to NULL. However due to an open issue in django-cacheops package, the related querysets are not invalidated upon deletion of parent model. Refer - Suor/django-cacheops#348. So we have to manually invalidate the cached querysets.
I guess cacheops could do something like:
pre_delete
signal handler that checks if there are any FKs in other models pointing to the deleted modelpost_delete
iterate the objects from thread locals and callinvalidate_obj()
on eachThis could be quite slow?
The text was updated successfully, but these errors were encountered: