I have altered the default manager on some of the objects which a GenericForeignKey()
can reference such that those objects may no longer appear within that default manager.
I have other managers which will be able to find these deleted objects, but I see no way to tell the content types framework about them. Is this possible?
I am implementing 'soft deletion' with some models which involves the following managers:
from django.db import models
SDManager(models.Manager):
def get_query_set(self):
return super(SDManager, self).get_query_set().filter(is_deleted=False)
SDDeletedManager(models.Manager):
def get_query_set(self):
return super(SDDeletedManager, self).get_query_set().filter(is_deleted=True)
This allows me to do the following:
SDModel(models.Model):
# ...
objects = SDManager() # Only non (soft) deleted objects
all_objects = models.Manager() # The default manager
deleted_objects = SDDeletedManager() # Only (soft) deleted objects
When using a GenericForeignKey()
field in a model to reference an object defined such as SDModel
, it uses the _default_manager
attribute which evaluates to the objects
manager, to get the reference. This means it looses references when objects are soft deleted.
This was one of the main reasons I was using GenericForeignKey()
fields. A solution I have been milling over is implementing a lesser version of the content types framework, so that I can define my own get_object()
which uses the all_objects
manager to access the references object.
So my question really is:
Is it possible to use a non-default manager with the existing content types framework so that it finds the soft deleted objects, or will I have to re implement all the parts I need from scratch?
I have the exact same issue as you, and after diving into the documentation/source it looks like Django does not provide an out of the box way to do this. The simplest method I found was to subclass GenericForeignKey
and then override the __get__
method.
The troublesome line is where it calls:
rel_obj = ct.get_object_for_this_type(pk=getattr(instance, self.fk_field))
So this line needs to be rewritten as:
rel_obj = ct.model_class().all_objects.get(pk=getattr(instance, self.fk_field))
It's a little bit hackish but it works, and you then get to use the full power of GenericForeignKey like you usually would.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With