add place csv export

This commit is contained in:
2026-10-24 02:11:09 +02:00
parent 723da9aa38
commit 87e6e38291
+27 -1
View File
@@ -1,5 +1,7 @@
import csv
import struct import struct
from django.db.models import Count
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from ninja import Router from ninja import Router
from ninja.decorators import decorate_view from ninja.decorators import decorate_view
@@ -9,7 +11,7 @@ from games.decorators import require_game_enabled
from .canvas import read_canvas from .canvas import read_canvas
from .gif import build_evolution_gif from .gif import build_evolution_gif
from .models import PlaceSettings from .models import PixelPlacement, PlaceSettings
router = Router() router = Router()
@@ -37,3 +39,27 @@ def canvas(request: HttpRequest, event_path: str):
def evolution_gif(request: HttpRequest, event_path: str): def evolution_gif(request: HttpRequest, event_path: str):
"""Admin-only: replays the full placement history as an animated GIF.""" """Admin-only: replays the full placement history as an animated GIF."""
return HttpResponse(build_evolution_gif(request.event), content_type="image/gif") return HttpResponse(build_evolution_gif(request.event), content_type="image/gif")
@router.get(f"{PREFIX}/placements.csv", auth=django_auth_is_staff)
@decorate_view(require_game_enabled(path="place"))
def placements_csv(request: HttpRequest, event_path: str):
"""Admin-only: pixel placement count per player, most active first."""
rows = (
PixelPlacement.objects.filter(event=request.event)
.values("player__username")
.annotate(count=Count("id"))
.order_by("-count", "player__username")
)
# text/plain so browsers render it inline - most force-download text/csv
response = HttpResponse(content_type="text/plain; charset=utf-8")
writer = csv.writer(response)
writer.writerow(["username", "placements"])
for row in rows:
writer.writerow(
[
row["player__username"],
row["count"],
]
)
return response