Skip to content

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

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?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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