diff --git a/cacheops/tree.py b/cacheops/tree.py index 6334ac73..de2638d8 100644 --- a/cacheops/tree.py +++ b/cacheops/tree.py @@ -159,9 +159,13 @@ def table_for(alias): # Add any subqueries used for annotation if qs.query.annotations: - subqueries = (query_dnf(getattr(q, 'query', None)) - for q in qs.query.annotations.values() if isinstance(q, Subquery)) - dnfs_.update(join_with(lcat, subqueries)) + sub_dnfs = [] + for q in qs.query.annotations.values(): + if isinstance(q, Subquery): + sub_dnfs.append(query_dnf(getattr(q, 'query', None))) + elif isinstance(q, Query): + sub_dnfs.append(query_dnf(q)) + dnfs_.update(join_with(lcat, sub_dnfs) or {}) return dnfs_ diff --git a/tests/tests.py b/tests/tests.py index 33f35945..f99f8e26 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -643,6 +643,18 @@ def test_365(self): categories = Category.objects.cache().annotate(newest_post=Subquery(newest_post[:1])) self.assertEqual(categories[0].newest_post, post.pk) + def test_366(self): + """ + Check that dnfs() detects table dependencies from Subquery annotations. + Django 6.0+ resolves Subquery into raw Query objects in qs.query.annotations, so this + verifies detection works regardless of how the annotation is stored. + """ + from cacheops.tree import dnfs + + newest_post = Post.objects.filter(category=OuterRef('pk')).order_by('-pk').values('pk') + qs = Category.objects.cache().annotate(newest_post=Subquery(newest_post[:1])) + self.assertEqual(dnfs(qs), {Category._meta.db_table: [{}], Post._meta.db_table: [{}]}) + @unittest.skipIf(platform.python_implementation() == "PyPy", "dill doesn't do that in PyPy") def test_385(self): Client.objects.create(name='Client Name')