from django.views.generic import TemplateView from django.urls import reverse_lazy from django.views.generic import UpdateView, DeleteView, CreateView, ListView, DetailView from cards.models import Card from trades.models import TradeOffer class CardDetailView(DetailView): model = Card template_name = "cards/card_detail.html" context_object_name = "card" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) card = self.get_object() # Count of trade offers where the card appears as a "have" in a trade. context['trade_offer_have_count'] = TradeOffer.objects.filter( trade_offer_have_cards__card=card ).distinct().count() # Count of trade offers where the card appears as a "want" in a trade. context['trade_offer_want_count'] = TradeOffer.objects.filter( trade_offer_want_cards__card=card ).distinct().count() return context class TradeOfferHaveCardListView(ListView): model = TradeOffer template_name = "cards/_trade_offer_list.html" context_object_name = "trade_offers" paginate_by = 6 def get_queryset(self): card_id = self.kwargs.get("pk") order_param = self.request.GET.get("order", "newest") ordering = "-updated_at" if order_param == "newest" else "updated_at" return TradeOffer.objects.filter( trade_offer_have_cards__card_id=card_id ).order_by(ordering).distinct() def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['side'] = 'have' return context class TradeOfferWantCardListView(ListView): model = TradeOffer template_name = "cards/_trade_offer_list.html" context_object_name = "trade_offers" paginate_by = 6 def get_queryset(self): card_id = self.kwargs.get("pk") order_param = self.request.GET.get("order", "newest") ordering = "-updated_at" if order_param == "newest" else "updated_at" return TradeOffer.objects.filter( trade_offer_want_cards__card_id=card_id ).order_by(ordering).distinct() def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['side'] = 'want' return context class CardListView(ListView): model = Card paginate_by = 100 # For non-grouped mode; grouping mode will override default pagination. context_object_name = "cards" def get_template_names(self): if self.request.headers.get("x-requested-with") == "XMLHttpRequest": return ["cards/_card_list.html"] return ["cards/card_list.html"] def get_ordering(self): order = self.request.GET.get("order", "absolute") if order == "alphabetical": return "name" elif order == "rarity": return "-rarity_level" else: # absolute ordering return "id" def get_queryset(self): qs = super().get_queryset() ordering = self.get_ordering() qs = qs.order_by(ordering) return qs.prefetch_related("decks").distinct() def get_paginate_by(self, queryset): group_by = self.request.GET.get("group_by") if group_by in ("deck", "cardset", "rarity"): # When grouping is enabled, we want to paginate manually so disable default pagination. return None return self.paginate_by def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) order = self.request.GET.get("order", "absolute") group_by = self.request.GET.get("group_by") context["order"] = order context["group_by"] = group_by if group_by in ("deck", "cardset", "rarity"): # Fetch the complete queryset (no slicing) full_qs = self.get_queryset() all_cards = list(full_qs) flat_cards = [] if group_by == "deck": # Each card may belong to multiple decks – reproduce the existing logic. for card in all_cards: for deck in card.decks.all(): flat_cards.append({"group": deck.name, "card": card}) flat_cards.sort(key=lambda x: x["group"].lower()) elif group_by == "cardset": for card in all_cards: flat_cards.append({"group": card.cardset, "card": card}) flat_cards.sort(key=lambda x: x["group"].lower()) elif group_by == "rarity": for card in all_cards: flat_cards.append({"group": card.rarity_level, "card": card}) flat_cards.sort(key=lambda x: x["group"], reverse=True) total_cards = len(flat_cards) try: page_number = int(self.request.GET.get("page", 1)) if page_number < 1: page_number = 1 except ValueError: page_number = 1 per_page = 96 start = (page_number - 1) * per_page end = page_number * per_page page_flat_cards = flat_cards[start:end] # Reassemble the flat list into grouped structure for just this page. page_groups = [] for item in page_flat_cards: group_value = item["group"] card_obj = item["card"] if page_groups and page_groups[-1]["group"] == group_value: page_groups[-1]["cards"].append(card_obj) else: page_groups.append({"group": group_value, "cards": [card_obj]}) context["groups"] = page_groups # Set up custom pagination context. from math import ceil num_pages = ceil(total_cards / per_page) page_obj = { "number": page_number, "has_previous": page_number > 1, "has_next": page_number < num_pages, "previous_page_number": page_number - 1 if page_number > 1 else None, "next_page_number": page_number + 1 if page_number < num_pages else None, "paginator": { "num_pages": num_pages, }, } context["page_obj"] = page_obj context["is_paginated"] = total_cards > per_page context["total_cards"] = total_cards # Optionally, keep the full queryset in object_list. context["object_list"] = full_qs return context return context