feat: add scouting search sorting and pagination
This commit is contained in:
@ -1,11 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Exists, OuterRef, Prefetch
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
|
||||
from .forms import PlayerSearchForm
|
||||
from .models import Player, PlayerSeason
|
||||
|
||||
PAGE_SIZE = 20
|
||||
PLAYER_SORTS = {
|
||||
"name_asc",
|
||||
"name_desc",
|
||||
"age_youngest",
|
||||
"height_desc",
|
||||
"weight_desc",
|
||||
}
|
||||
CONTEXT_SORTS = {
|
||||
"points_desc": "points",
|
||||
"assists_desc": "assists",
|
||||
"ts_pct_desc": "ts_pct",
|
||||
"blocks_desc": "blocks",
|
||||
}
|
||||
|
||||
|
||||
def sort_players(players, sort_key: str, context_filters_used: bool):
|
||||
if sort_key not in PLAYER_SORTS | set(CONTEXT_SORTS):
|
||||
sort_key = "name_asc"
|
||||
|
||||
if sort_key == "name_asc":
|
||||
players.sort(key=lambda player: player.full_name.casefold())
|
||||
return sort_key
|
||||
if sort_key == "name_desc":
|
||||
players.sort(key=lambda player: player.full_name.casefold(), reverse=True)
|
||||
return sort_key
|
||||
if sort_key == "age_youngest":
|
||||
players.sort(
|
||||
key=lambda player: (
|
||||
player.birth_date is None,
|
||||
-(player.birth_date.toordinal()) if player.birth_date else 0,
|
||||
player.full_name.casefold(),
|
||||
)
|
||||
)
|
||||
return sort_key
|
||||
if sort_key == "height_desc":
|
||||
players.sort(
|
||||
key=lambda player: (
|
||||
player.height_cm is None,
|
||||
-(player.height_cm or Decimal("0")),
|
||||
player.full_name.casefold(),
|
||||
)
|
||||
)
|
||||
return sort_key
|
||||
if sort_key == "weight_desc":
|
||||
players.sort(
|
||||
key=lambda player: (
|
||||
player.weight_kg is None,
|
||||
-(player.weight_kg or Decimal("0")),
|
||||
player.full_name.casefold(),
|
||||
)
|
||||
)
|
||||
return sort_key
|
||||
|
||||
if not context_filters_used:
|
||||
players.sort(key=lambda player: player.full_name.casefold())
|
||||
return "name_asc"
|
||||
|
||||
stat_name = CONTEXT_SORTS[sort_key]
|
||||
players.sort(
|
||||
key=lambda player: (
|
||||
getattr(getattr(getattr(player, "matching_context", None), "stats", None), stat_name, None) is None,
|
||||
-(
|
||||
getattr(getattr(getattr(player, "matching_context", None), "stats", None), stat_name)
|
||||
or Decimal("0")
|
||||
),
|
||||
player.full_name.casefold(),
|
||||
)
|
||||
)
|
||||
return sort_key
|
||||
|
||||
|
||||
def player_list(request):
|
||||
form = PlayerSearchForm(request.GET or None)
|
||||
@ -15,9 +89,11 @@ def player_list(request):
|
||||
.order_by("full_name")
|
||||
)
|
||||
context_filters_used = False
|
||||
requested_sort = request.GET.get("sort") or "name_asc"
|
||||
|
||||
if form.is_valid():
|
||||
data = form.cleaned_data
|
||||
requested_sort = data["sort"] or "name_asc"
|
||||
|
||||
if data["name"]:
|
||||
queryset = queryset.filter(full_name__icontains=data["name"])
|
||||
@ -153,12 +229,23 @@ def player_list(request):
|
||||
for player in players:
|
||||
player.matching_context = next(iter(player.matching_contexts), None)
|
||||
|
||||
active_sort = sort_players(players, requested_sort, context_filters_used)
|
||||
paginator = Paginator(players, PAGE_SIZE)
|
||||
page_obj = paginator.get_page(request.GET.get("page"))
|
||||
query_without_page = request.GET.copy()
|
||||
query_without_page.pop("page", None)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"scouting/player_list.html",
|
||||
{
|
||||
"form": form,
|
||||
"players": players,
|
||||
"players": page_obj.object_list,
|
||||
"page_obj": page_obj,
|
||||
"active_sort": active_sort,
|
||||
"total_results": paginator.count,
|
||||
"query_without_page": query_without_page.urlencode(),
|
||||
"context_sorting_enabled": context_filters_used,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user