Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtering on related manager when using prefetch_related with explicit queryset on a ClusterableModel returns wrong results #170

Open
maqnius opened this issue Jan 30, 2023 · 1 comment

Comments

@maqnius
Copy link

maqnius commented Jan 30, 2023

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)>]
@maqnius maqnius changed the title Filtering on related manager when using prefetch_related in combination with select_related on ClusterableModel return wrong results Filtering on related manager when using prefetch_related in combination with select_related on ClusterableModel returns wrong results Jan 30, 2023
@maqnius maqnius changed the title Filtering on related manager when using prefetch_related in combination with select_related on ClusterableModel returns wrong results Filtering on related manager when using prefetch_related in combination with select_related on a ClusterableModel returns wrong results Jan 30, 2023
@maqnius maqnius changed the title Filtering on related manager when using prefetch_related in combination with select_related on a ClusterableModel returns wrong results Filtering on related manager when using prefetch_related with explicit queryset on a ClusterableModel returns wrong results Jan 30, 2023
@tituomin
Copy link

tituomin commented May 4, 2023

Also seeing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants