Some optimizations to trade_offers to reduce loading times
This commit is contained in:
parent
0ac8ac8d5c
commit
9ce5d525b3
13 changed files with 255 additions and 222 deletions
102
home/views.py
102
home/views.py
|
|
@ -14,106 +14,58 @@ from django.http import HttpResponseRedirect
|
|||
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)
|
||||
|
||||
context["cards"] = Card.objects.all() \
|
||||
.order_by("name", "rarity__pk") \
|
||||
.select_related("rarity", "cardset") \
|
||||
.prefetch_related("decks")
|
||||
context["cards"] = Card.objects.all().order_by("name", "rarity__pk")
|
||||
|
||||
# Reuse base trade offer queryset for market stats
|
||||
base_offer_qs = self.get_base_trade_offer_queryset().filter(is_closed=False)
|
||||
base_offer_qs = TradeOffer.objects.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]
|
||||
recent_offers_qs = base_offer_qs.order_by("-created_at")
|
||||
context["recent_offers"] = recent_offers_qs[:6]
|
||||
|
||||
# Most Offered Cards
|
||||
context["most_offered_cards"] = (
|
||||
Card.objects.filter(tradeofferhavecard__isnull=False)
|
||||
Card.objects_no_prefetch.filter(tradeofferhavecard__isnull=False)
|
||||
.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
||||
.order_by("-offer_count")
|
||||
.select_related("rarity", "cardset")
|
||||
.prefetch_related("decks")[:5]
|
||||
.order_by("-offer_count", "?")[:6]
|
||||
)
|
||||
|
||||
# Most Wanted Cards
|
||||
context["most_wanted_cards"] = (
|
||||
Card.objects.filter(tradeofferwantcard__isnull=False)
|
||||
Card.objects_no_prefetch.filter(tradeofferwantcard__isnull=False)
|
||||
.annotate(offer_count=Sum("tradeofferwantcard__quantity"))
|
||||
.order_by("-offer_count")
|
||||
.select_related("rarity", "cardset")
|
||||
.prefetch_related("decks")[:5]
|
||||
.order_by("-offer_count", "?")[:6]
|
||||
)
|
||||
|
||||
# Least Offered Cards
|
||||
context["least_offered_cards"] = (
|
||||
Card.objects.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
||||
.order_by("offer_count", "?")[:5]
|
||||
Card.objects_no_prefetch.annotate(offer_count=Sum("tradeofferhavecard__quantity"))
|
||||
.order_by("offer_count", "?")[:6]
|
||||
)
|
||||
|
||||
# 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]
|
||||
featured["All"] = base_offer_qs.order_by("created_at")[:6]
|
||||
|
||||
normalized_ids = list(
|
||||
Rarity.objects.filter(pk__lte=5).values_list("normalized_id", flat=True).distinct()
|
||||
)
|
||||
|
||||
rarity_map = {rarity.normalized_id: rarity.icons for rarity in Rarity.objects.filter(pk__lte=5)}
|
||||
|
||||
# For each normalized id (sorted descending), filter base offers that have a related card with that rarity.
|
||||
for norm in sorted(normalized_ids, reverse=True):
|
||||
offers_qs = base_offer_qs.filter(
|
||||
have_cards__rarity__normalized_id=norm
|
||||
# or want cards, but all offers share the same rarity so checking have_cards is enough
|
||||
# TODO: attach rarity to offer so we don't need to do this
|
||||
).order_by("created_at").distinct()[:6]
|
||||
icon_label = rarity_map.get(norm)
|
||||
if icon_label:
|
||||
featured[icon_label] = offers[:5]
|
||||
featured[icon_label] = offers_qs
|
||||
|
||||
context["featured_offers"] = featured
|
||||
|
||||
return context
|
||||
Loading…
Add table
Add a link
Reference in a new issue