I have the following 2 Django models:
from mptt.models import MPTTModel, TreeForeignKey
from django.db import models
from django.db.models import Q
class Model1(MPTTModel):
random_field = models.IntegerField()
parent = TreeForeignKey('self', null=True, blank=True)
class Model2(models.Model):
model_1 = models.ManyToManyField(Model1)
@staticmethod
def descendants_queryset(model1):
q = Q()
for curr_descendant in model1.get_descendants:
q |= Q(model_1=curr_descendant)
return q
I have created instances like this:
>>> a = Model2.objects.create()
>>> b = Model1.objects.create(random_field=1, parent=None)
>>> c = Model1.objects.create(random_field=2, parent=b)
>>> d = Model1.objects.create(random_field=3, parent=b)
>>> a.model_1.add(c)
>>> a.pk
3
When I do a normal queryset filter and when I use the Q() expression it produces the same results (as expected):
>>> [i.pk for i in Model2.objects.filter(pk=3)]
[3]
>>> [i.pk for i in Model2.objects.filter(Model2.descendants_queryset(b), pk=3)]
[3]
But when I add another instance of the Model1 to the ManyToMany relationship, I see a weird duplication only when I filter using the Q() expression:
>>> a.model_1.add(d)
>>> [i.pk for i in Model2.objects.filter(pk=3)]
[3]
>>> [i.pk for i in Model2.objects.filter(Model2.descendants_queryset(b), pk=3)]
[3, 3]
I'm confused why this duplication is happening. It seems like a bug to me. I can obviously work around it by adding a .distinct()
to the queryset. But that seems like it should not be necessary. Why is this happening and what is the proper solution?