diff --git a/comicsdb/views/publisher.py b/comicsdb/views/publisher.py index ec333888..9ffe406c 100644 --- a/comicsdb/views/publisher.py +++ b/comicsdb/views/publisher.py @@ -2,6 +2,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.db.models import Count, OuterRef, Subquery +from django.db.models.functions import Coalesce from django.shortcuts import get_object_or_404 from django.urls import reverse_lazy from django.views.generic import DetailView, ListView @@ -115,13 +116,13 @@ def get_context_data(self, **kwargs): # Paginate imprints - only load first batch if imprint_count > 0: context["imprints"] = publisher.imprints.annotate( - series_count=Subquery(_imprint_series_count_sq) + series_count=Coalesce(Subquery(_imprint_series_count_sq), 0) )[:DETAIL_PAGINATE_BY] # Paginate universes - only load first batch if universe_count > 0: context["universes"] = publisher.universes.annotate( - issue_count=Subquery(_universe_issue_count_sq) + issue_count=Coalesce(Subquery(_universe_issue_count_sq), 0) )[:DETAIL_PAGINATE_BY] return context @@ -172,9 +173,9 @@ class PublisherImprintsLoadMore(LazyLoadMixin): slug_context_name = "publisher_slug" def get_queryset(self, parent_object, offset, limit): - return parent_object.imprints.annotate(series_count=Subquery(_imprint_series_count_sq))[ - offset : offset + limit - ] + return parent_object.imprints.annotate( + series_count=Coalesce(Subquery(_imprint_series_count_sq), 0) + )[offset : offset + limit] class PublisherUniversesLoadMore(LazyLoadMixin): @@ -187,6 +188,6 @@ class PublisherUniversesLoadMore(LazyLoadMixin): slug_context_name = "publisher_slug" def get_queryset(self, parent_object, offset, limit): - return parent_object.universes.annotate(issue_count=Subquery(_universe_issue_count_sq))[ - offset : offset + limit - ] + return parent_object.universes.annotate( + issue_count=Coalesce(Subquery(_universe_issue_count_sq), 0) + )[offset : offset + limit] diff --git a/tests/comicsdb/test_publisher_views.py b/tests/comicsdb/test_publisher_views.py index bc0da389..d0cbddd2 100644 --- a/tests/comicsdb/test_publisher_views.py +++ b/tests/comicsdb/test_publisher_views.py @@ -77,6 +77,23 @@ def test_publisher_detail_with_imprint_and_universe_counts( assert resp.context["universes"][0].issue_count == 1 +def test_publisher_detail_with_empty_imprint_and_universe( + dc_comics, vertigo_imprint, earth_2_universe, auto_login_user +): + """Regression test: imprints/universes with zero series/issues must render. + + The correlated-subquery annotation returns NULL (not 0) when an imprint + has no series or a universe has no issues, which also crashed the + ``{% blocktrans count %}`` tag (e.g. /publisher/dc-comics/ in production + where an imprint/universe existed with nothing tagged to it yet). + """ + client, _ = auto_login_user() + resp = client.get(f"/publisher/{dc_comics.slug}/") + assert resp.status_code == HTML_OK_CODE + assert resp.context["imprints"][0].series_count == 0 + assert resp.context["universes"][0].issue_count == 0 + + def test_publisher_redirect(dc_comics, auto_login_user): client, _ = auto_login_user() resp = client.get(f"/publisher/{dc_comics.pk}/")