When applying prefetch_related with a given queryset , the results of the related manager on the returned instances do return the wrong results if .filter(..) is applied instead of the (cached) .all() query.
Probably anything than .all() will return wrong results.
Unfortunately I could not really figure out where the bug exactly is located, because I'm too unfamiliar with this part of the django code base, but I guess it is related to the modelcluster.fields.ChildObjectsDescriptor.
This issue is related to and probably a duplicate of #103, but I narrowed down the steps to reproduce the bug and I hope this will get more attention then.
Steps to Reproduce
Models
from django.db import models
from modelcluster.models import ClusterableModel
from modelcluster.fields import ParentalKey
class Parent(ClusterableModel):
pass
class Child(models.Model):
parent = ParentalKey(Parent, related_name="children", on_delete=models.PROTECT)
Test
class TestPrefetch(TestCase):
def setUp(self):
# Create parents
parent_1 = Parent.objects.create()
parent_2 = Parent.objects.create()
# Create a children for each parent
Child.objects.create(parent=parent_1)
Child.objects.create(parent=parent_2)
def test_prefetch(self):
parents = Parent.objects.prefetch_related(
Prefetch("children", queryset=Child.objects.all())
)
# Select an instance
parent_1 = parents[0]
self.assertListEqual(
list(parent_1.children.filter()),
list(parent_1.children.all()),
)
Expected Result
parent_1.children.filter() and parent_1.children.all() should return the same queryset containing only the children of the instance parent_1.
Actual Result
parent_1.children.filter() returns all children in the database, also the one related to parent_2 only. Any further filtering is applied to this queryset and will yield wrong results.
AssertionError: Lists differ: [<Child: Child object (1)>, <Child: Child object (2)>] != [<Child: Child object (1)>]
When applying
prefetch_relatedwith a givenqueryset, the results of the related manager on the returned instances do return the wrong results if.filter(..)is applied instead of the (cached).all()query.Probably anything than
.all()will return wrong results.Unfortunately I could not really figure out where the bug exactly is located, because I'm too unfamiliar with this part of the django code base, but I guess it is related to the
modelcluster.fields.ChildObjectsDescriptor.This issue is related to and probably a duplicate of #103, but I narrowed down the steps to reproduce the bug and I hope this will get more attention then.
Steps to Reproduce
Models
Test
Expected Result
parent_1.children.filter()andparent_1.children.all()should return the same queryset containing only the children of the instanceparent_1.Actual Result
parent_1.children.filter()returns all children in the database, also the one related toparent_2only. Any further filtering is applied to this queryset and will yield wrong results.