Skip to content

get operation raises DoesNotExist raised when related FK with on_delete=SET_NULL is deleted #348

Open
@mrmachine

Description

@mrmachine
# models
class User(Model):
    active_device = ForeignKey(Device, on_delete=SET_NULL
    ...

# shell
In [3]: u = User.objects.cache().get(pk=4473)

In [4]: u.active_device
Out[4]: <Device: ...>

In [5]: u.active_device.delete()

In [6]: u = User.objects.cache().get(pk=4473)

In [7]: u.active_device
---------------------------------------------------------------------------
DoesNotExist                              Traceback (most recent call last)
<ipython-input-7-a017d853d610> in <module>()
----> 1 u.active_device

.../venv/lib/python2.7/site-packages/django/db/models/fields/related.py in __get__(self, instance, instance_type)
    318                     qs = qs.filter(extra_filter, **params)
    319                 # Assuming the database enforces foreign keys, this won't fail.
--> 320                 rel_obj = qs.get()
    321                 if not self.field.rel.multiple:
    322                     setattr(rel_obj, self.field.related.get_cache_name(), instance)

.../src/django-cacheops/cacheops/query.py in get(self, *args, **kwargs)
    344             qs = self
    345 
--> 346         return qs._no_monkey.get(qs, *args, **kwargs)
    347 
    348     if django.VERSION >= (1, 6):

.../venv/lib/python2.7/site-packages/django/db/models/query.py in get(self, *args, **kwargs)
    308             raise self.model.DoesNotExist(
    309                 "%s matching query does not exist." %
--> 310                 self.model._meta.object_name)
    311         raise self.model.MultipleObjectsReturned(
    312             "get() returned more than one %s -- it returned %s!" %

DoesNotExist: Device matching query does not exist.

I guess cacheops could do something like:

  • add a pre_delete signal handler that checks if there are any FKs in other models pointing to the deleted model
  • add a list of those objects to thread locals
  • in post_delete iterate the objects from thread locals and call invalidate_obj() on each

This could be quite slow?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions