From 2af54dfbaa010c481978c65dc63e451379d916db Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:44:23 +0200 Subject: [PATCH] Improve card ordering --- .../tests/test_views/test_card_views.py | 31 +++++++++++++------ backend/spellbook/tests/testing.py | 19 ++++++++++++ backend/spellbook/views/cards.py | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/backend/spellbook/tests/test_views/test_card_views.py b/backend/spellbook/tests/test_views/test_card_views.py index 7e48fb7c..5fff6624 100644 --- a/backend/spellbook/tests/test_views/test_card_views.py +++ b/backend/spellbook/tests/test_views/test_card_views.py @@ -66,13 +66,24 @@ def test_cards_detail_view(self): def test_cards_list_view_ordering(self): self.generate_and_publish_variants() - response = self.client.get('/cards?ordering=-variant_count', follow=True) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.get('Content-Type'), 'application/json') - result = json.loads(response.content, object_hook=json_to_python_lambda) - card_count = Card.objects.count() - self.assertEqual(len(result.results), card_count) - previous_variant_count = 0 - for i in range(card_count): - self.card_assertions(result.results[i]) - self.assertGreaterEqual(result.results[i].variant_count, previous_variant_count) + for ordering, assertion in [ + ('variant_count', lambda a, b: self.assertGreaterEqual(a.variant_count, b.variant_count)), + ('-variant_count', lambda a, b: self.assertLessEqual(a.variant_count, b.variant_count)), + ('name', lambda a, b: self.assertGreaterEqual(a.name, b.name)), + ('-name', lambda a, b: self.assertLessEqual(a.name, b.name)), + ]: + response = self.client.get(f'/cards?ordering={ordering}', follow=True) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get('Content-Type'), 'application/json') + result = json.loads(response.content, object_hook=json_to_python_lambda) + card_count = Card.objects.count() + self.assertEqual(len(result.results), card_count) + previous_variant = None + variant_count_values = set[int()]() + for i in range(card_count): + self.card_assertions(result.results[i]) + if i > 0: + assertion(result.results[i], previous_variant) + previous_variant = result.results[i] + variant_count_values.add(result.results[i].variant_count) # type: ignore + self.assertGreater(len(variant_count_values), 1) diff --git a/backend/spellbook/tests/testing.py b/backend/spellbook/tests/testing.py index 0f54bf85..a5fa6cf8 100644 --- a/backend/spellbook/tests/testing.py +++ b/backend/spellbook/tests/testing.py @@ -2,6 +2,9 @@ import uuid from functools import reduce from collections import defaultdict + +from django.db.models import Count, OuterRef, Subquery +from django.db.models.functions import Coalesce from common.testing import TestCaseMixin as BaseTestCaseMixin from django.conf import settings from spellbook.models import Card, Feature, Combo, CardInCombo, Template, TemplateInCombo @@ -25,10 +28,26 @@ def bulk_serialize_variants(self, q=None, extra_fields=[]): q = Variant.objects.all() Variant.objects.bulk_serialize(q, serializer=VariantSerializer, fields=extra_fields) # type: ignore + def update_variants_count(self): + Card.objects.update( + variant_count=Coalesce( + Subquery( + Variant + .objects + .filter(uses=OuterRef('pk'), status__in=('OK', 'E')) + .values('uses') + .annotate(total=Count('pk')) + .values('total'), + ), + 0, + ), + ) + def generate_and_publish_variants(self): self.generate_variants() self.bulk_serialize_variants() Variant.objects.update(status=Variant.Status.OK) + self.update_variants_count() def save_combo_model(self, model: dict[tuple[str, ...] | str, tuple[str, ...]]): card_ids_by_name: dict[str, int] = {} diff --git a/backend/spellbook/views/cards.py b/backend/spellbook/views/cards.py index 47020cc7..ea48cc1a 100644 --- a/backend/spellbook/views/cards.py +++ b/backend/spellbook/views/cards.py @@ -7,5 +7,5 @@ class CardViewSet(viewsets.ReadOnlyModelViewSet): queryset = CardDetailSerializer.prefetch_related(Card.objects) serializer_class = CardDetailSerializer - ordering = ['variant_count'] + ordering = ['variant_count', 'name'] filter_backends = [NameAutocompleteQueryFilter, OrderingFilterWithNullsLast]