Subclass A Django Manyrelatedmanager A.k.a. Manytomanyfield
Solution 1:
You can create proxy model of SelfRefrencingModel
and override the default manager. Then use this proxy model in ManyToManyField
.
Subclassing ManyToManyField
will not help you because for the resulting queryset ManyRelatedManger
is responsible.
Proxy model approach:
from django.db import models
classA(models.Model):
children = models.ManyToManyField('AProxy')
name = models.TextField()
deleted = models.NullBooleanField(null=True)
classFilterDeletedManager(models.Manager):
defget_queryset(self):
qs = super(FilterDeletedManager, self).get_query_set()
return qs.filter(deleted__isnull=True)
classAProxy(A):
objects = FilterDeletedManager()
classMeta:
proxy = True
Caveat with this approach is that now django expects AProxy
instances for children
field.
So maybe better readable and maintainable approach will be to add another attribute in __init__
.
from django.db import models
classA(models.Model):
children = models.ManyToManyField('self')
name = models.TextField()
deleted = models.NullBooleanField(null=True)
def__init__(self, *args, **kwargs):
super(A, self).__init__(*args, **kwargs)
self.deleted_null_children = self.children.filter(deleted__isnull=True)
Solution 2:
Here is my solution. @beezz, you may be correct to use a Proxy Model to do this, but I haven't used a Proxy Model before for this pattern, so this is how I solved this:
classSelfRefrencingQuerySet(models.query.QuerySet):
passclassSelfRefrencingManager(BaseManager):
defget_queryset(self):
return SelfRefrencingQuerySet(self.model, self._db).filter(
deleted__isnull=True)
classSelfRefrencingBaseModel(models.Model):
children = models.ManyToManyField('self', blank=True, symmetrical=False,
related_name='parents')
# Manager
objects = SelfRefrencingManager()
objects_all = models.Manager() # So you still have acccess to the# default Manager
Solution 3:
If your intention is to use this with Django Admin or ModelForm
; you don't need to subclass the ManyToManyField
. See the django documentation
classSelfRefrencingModel(models.Model):
children = models.ManyToManyField('self', blank=True, symmetrical=False,
related_name='parents', limit_choices_to={'deleted': False}))
Note: If deleted
is a BooleanField
it has to be True
or False
. It can't be None
/NULL
.
beezz's idea of using a Proxy Model is also a good one.
What I sometimes do is to customise the default managerclassMyModelManager(models.Manager):
use_for_related_fields = Truedefget_queryset(self):
qs = super(MyModelManager, self).get_queryset()
return qs.filter(deleted=False)
classMyModelManager(models.Model):
objects = MyModelManager()
_objects = models.Manger()
deleted = models.BooleanField(default=False)
By default deleted
objects will be hidden, but if need them in your queryset, you can use _objects
.
Post a Comment for "Subclass A Django Manyrelatedmanager A.k.a. Manytomanyfield"