pkmntrade.club/home/views.py

118 lines
No EOL
4.7 KiB
Python

from collections import defaultdict
from django.views.generic import TemplateView
from django.urls import reverse_lazy
from django.db.models import Count, Q, Prefetch, Sum, F, IntegerField, Value, BooleanField, Case, When
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from trades.models import TradeOffer, TradeAcceptance, TradeOfferHaveCard, TradeOfferWantCard
from cards.models import Card, CardSet, Rarity
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.template.response import TemplateResponse
from django.http import HttpResponseRedirect
@method_decorator(cache_page(60), name='get')
class HomePageView(TemplateView):
template_name = "home/home.html"
def get_base_trade_offer_queryset(self):
"""
Returns a queryset for TradeOffer that includes prefetches and denormalized aggregates.
"""
active_states = [
TradeAcceptance.AcceptanceState.ACCEPTED,
TradeAcceptance.AcceptanceState.SENT,
TradeAcceptance.AcceptanceState.RECEIVED,
TradeAcceptance.AcceptanceState.THANKED_BY_INITIATOR,
TradeAcceptance.AcceptanceState.THANKED_BY_ACCEPTOR,
TradeAcceptance.AcceptanceState.THANKED_BY_BOTH,
]
have_cards_prefetch = Prefetch(
'have_cards',
queryset=Card.objects.annotate(
trade_offer_count=Count("trade_offers_have")
).order_by("trade_offer_count", "id")
)
want_cards_prefetch = Prefetch(
'want_cards',
queryset=Card.objects.annotate(
trade_offer_count=Count("trade_offers_want")
).order_by("trade_offer_count", "id")
)
qs = (
TradeOffer.objects.all()
.prefetch_related(
have_cards_prefetch,
"have_cards__decks",
"have_cards__rarity",
"have_cards__cardset",
want_cards_prefetch,
"want_cards__decks",
"want_cards__rarity",
"want_cards__cardset",
"acceptances"
)
.select_related("initiated_by__user")
)
return qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add available_cards QuerySet so card_multiselect works properly.
context["available_cards"] = Card.objects.all() \
.order_by("name", "rarity__pk") \
.select_related("rarity", "cardset") \
.prefetch_related("decks")
# Reuse base trade offer queryset for market stats
base_offer_qs = self.get_base_trade_offer_queryset().filter(is_closed=False)
# Recent Offers
recent_offers_qs = base_offer_qs.order_by("-created_at")[:10]
context["recent_offers"] = list(recent_offers_qs)[:5]
# Most Offered Cards
context["most_offered_cards"] = (
Card.objects.filter(tradeofferhavecard__isnull=False)
.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
.order_by("-offer_count")
.select_related("rarity", "cardset")
.prefetch_related("decks")[:5]
)
# Most Wanted Cards
context["most_wanted_cards"] = (
Card.objects.filter(tradeofferwantcard__isnull=False)
.annotate(offer_count=Sum("tradeofferwantcard__quantity"))
.order_by("-offer_count")
.select_related("rarity", "cardset")
.prefetch_related("decks")[:5]
)
# Least Offered Cards
context["least_offered_cards"] = (
Card.objects.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
.order_by("offer_count", "?")[:5]
)
# Featured Offers grouped by rarity
all_offers = base_offer_qs.order_by("created_at")
featured = {}
featured["All"] = all_offers[:5]
grouped = defaultdict(list)
for offer in all_offers:
normalized_ids = {card.rarity.normalized_id for card in offer.have_cards.all() if card.rarity}
for norm in normalized_ids:
grouped[norm].append(offer)
norm_ids_available = list(grouped.keys())
rareness_qs = Rarity.objects.filter(pk__in=[6] + [nid for nid in norm_ids_available if nid != 6])
rarity_map = {rarity.pk: rarity.icons for rarity in rareness_qs}
for norm in sorted(grouped.keys(), reverse=True):
offers = grouped[norm]
icon_label = rarity_map.get(norm)
if icon_label:
featured[icon_label] = offers[:5]
context["featured_offers"] = featured
return context