feat(games): honor ?sort= on list_games + eager-load platform (#68)
This commit is contained in:
+8
-1
@@ -1,5 +1,6 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
@@ -48,6 +49,7 @@ from common.time import (
|
|||||||
)
|
)
|
||||||
from common.utils import build_dynamic_filter, paginate, safe_division, truncate
|
from common.utils import build_dynamic_filter, paginate, safe_division, truncate
|
||||||
from games.filters import parse_game_filter
|
from games.filters import parse_game_filter
|
||||||
|
from games.sorting import GAME_DEFAULT_SORT, GAME_SORTS, apply_sort, parse_find_filter
|
||||||
from games.forms import GameForm
|
from games.forms import GameForm
|
||||||
from games.models import Game
|
from games.models import Game
|
||||||
from games.views.general import use_custom_redirect
|
from games.views.general import use_custom_redirect
|
||||||
@@ -56,7 +58,7 @@ from games.views.playevent import create_playevent_tabledata
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def list_games(request: HttpRequest, search_string: str = "") -> HttpResponse:
|
def list_games(request: HttpRequest, search_string: str = "") -> HttpResponse:
|
||||||
games = Game.objects.order_by("-created_at")
|
games = Game.objects.select_related("platform")
|
||||||
|
|
||||||
# ── Structured filter (Stash-style JSON) ──
|
# ── Structured filter (Stash-style JSON) ──
|
||||||
filter_json = request.GET.get("filter", "")
|
filter_json = request.GET.get("filter", "")
|
||||||
@@ -86,6 +88,11 @@ def list_games(request: HttpRequest, search_string: str = "") -> HttpResponse:
|
|||||||
filters.append(Q(status=search_status))
|
filters.append(Q(status=search_status))
|
||||||
games = games.filter(build_dynamic_filter(filters, "|"))
|
games = games.filter(build_dynamic_filter(filters, "|"))
|
||||||
|
|
||||||
|
sort = apply_sort(games, parse_find_filter(request), GAME_SORTS, GAME_DEFAULT_SORT)
|
||||||
|
games = sort.queryset
|
||||||
|
for key in sort.unknown:
|
||||||
|
messages.warning(request, f"Unknown sort field '{key}' was ignored.")
|
||||||
|
|
||||||
games, page_obj, elided_page_range = paginate(request, games)
|
games, page_obj, elided_page_range = paginate(request, games)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ from zoneinfo import ZoneInfo
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.messages import get_messages
|
||||||
from django.test import RequestFactory
|
from django.test import RequestFactory
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from games.filters import FindFilter
|
from games.filters import FindFilter
|
||||||
from games.models import Game, Platform, Session
|
from games.models import Game, Platform, Session
|
||||||
@@ -137,3 +139,30 @@ class TestSortMapShapes:
|
|||||||
]:
|
]:
|
||||||
for token in default.split(","):
|
for token in default.split(","):
|
||||||
assert token.lstrip("-") in sort_map
|
assert token.lstrip("-") in sort_map
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def logged_client(client, django_user_model):
|
||||||
|
user = django_user_model.objects.create_user(username="u", password="p")
|
||||||
|
client.force_login(user)
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
class TestListGamesSort:
|
||||||
|
def test_sort_param_orders_rows(self, logged_client, two_games):
|
||||||
|
alpha, beta = two_games
|
||||||
|
response = logged_client.get(reverse("games:list_games"), {"sort": "-name"})
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.content.decode()
|
||||||
|
assert body.index("Beta") < body.index("Alpha")
|
||||||
|
|
||||||
|
def test_unknown_sort_emits_warning_message(self, logged_client, two_games):
|
||||||
|
response = logged_client.get(reverse("games:list_games"), {"sort": "bogus"})
|
||||||
|
assert response.status_code == 200
|
||||||
|
warnings = [str(m) for m in get_messages(response.wsgi_request)]
|
||||||
|
assert any("bogus" in w for w in warnings)
|
||||||
|
|
||||||
|
def test_valid_sort_emits_no_warning(self, logged_client, two_games):
|
||||||
|
response = logged_client.get(reverse("games:list_games"), {"sort": "name"})
|
||||||
|
warnings = [str(m) for m in get_messages(response.wsgi_request)]
|
||||||
|
assert warnings == []
|
||||||
|
|||||||
Reference in New Issue
Block a user