129 lines
No EOL
5.2 KiB
Python
129 lines
No EOL
5.2 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")
|
|
.annotate(
|
|
is_active=Case(
|
|
When(
|
|
Q(total_have_accepted__lt=F('total_have_quantity')) &
|
|
Q(total_want_accepted__lt=F('total_want_quantity')),
|
|
then=Value(True)
|
|
),
|
|
default=Value(False),
|
|
output_field=BooleanField()
|
|
)
|
|
)
|
|
)
|
|
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(manually_closed=False, is_active=True)
|
|
|
|
# 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 |