Files
ShooterHub/apps/sessions/views.py
2026-04-02 11:24:30 +02:00

144 lines
6.0 KiB
Python

from django.shortcuts import get_object_or_404
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .ballistics import compute_corrections
from .models import FreePracticeSession, PRSSession, PRSStage, SpeedShootingSession
from .serializers import (
FreePracticeSessionDetailSerializer,
FreePracticeSessionListSerializer,
FreePracticeSessionWriteSerializer,
PRSSessionDetailSerializer,
PRSSessionListSerializer,
PRSSessionWriteSerializer,
PRSStageSerializer,
SpeedShootingSessionDetailSerializer,
SpeedShootingSessionListSerializer,
SpeedShootingSessionWriteSerializer,
)
# ── PRS ───────────────────────────────────────────────────────────────────────
class PRSSessionViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
filterset_fields = ['date', 'is_public']
search_fields = ['name', 'location', 'notes', 'competition_name']
ordering_fields = ['date', 'created_at']
def get_queryset(self):
qs = (
PRSSession.objects
.filter(user=self.request.user)
.select_related('rig', 'ammo', 'reloaded_batch__recipe', 'reloaded_batch__powder', 'analysis')
)
if self.action != 'list':
qs = qs.prefetch_related('stages')
return qs
def get_serializer_class(self):
if self.action == 'list':
return PRSSessionListSerializer
if self.action in ('create', 'update', 'partial_update'):
return PRSSessionWriteSerializer
return PRSSessionDetailSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)
# ── Nested stage actions ──────────────────────────────────────────────────
@action(detail=True, methods=['get', 'post'], url_path='stages')
def stages(self, request, pk=None):
session = self.get_object()
if request.method == 'GET':
serializer = PRSStageSerializer(
session.stages.all(), many=True, context={'request': request}
)
return Response(serializer.data)
serializer = PRSStageSerializer(
data=request.data,
context={'request': request, 'session': session},
)
serializer.is_valid(raise_exception=True)
serializer.save(session=session)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@action(detail=True, methods=['get', 'patch', 'delete'],
url_path=r'stages/(?P<stage_pk>[^/.]+)')
def stage_detail(self, request, pk=None, stage_pk=None):
session = self.get_object()
stage = get_object_or_404(PRSStage, pk=stage_pk, session=session)
if request.method == 'GET':
return Response(PRSStageSerializer(stage, context={'request': request}).data)
if request.method == 'PATCH':
serializer = PRSStageSerializer(
stage, data=request.data, partial=True, context={'request': request}
)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
stage.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@action(detail=True, methods=['post'],
url_path=r'stages/(?P<stage_pk>[^/.]+)/compute-corrections')
def compute_corrections_action(self, request, pk=None, stage_pk=None):
session = self.get_object()
stage = get_object_or_404(PRSStage, pk=stage_pk, session=session)
return Response(compute_corrections(session, stage))
# ── Free Practice ─────────────────────────────────────────────────────────────
class FreePracticeSessionViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
filterset_fields = ['date', 'is_public']
search_fields = ['name', 'location', 'notes']
ordering_fields = ['date', 'created_at']
def get_queryset(self):
return (
FreePracticeSession.objects
.filter(user=self.request.user)
.select_related('rig', 'ammo', 'reloaded_batch__recipe', 'reloaded_batch__powder', 'analysis')
)
def get_serializer_class(self):
if self.action == 'list':
return FreePracticeSessionListSerializer
if self.action in ('create', 'update', 'partial_update'):
return FreePracticeSessionWriteSerializer
return FreePracticeSessionDetailSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)
# ── Speed Shooting ────────────────────────────────────────────────────────────
class SpeedShootingSessionViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
filterset_fields = ['date', 'is_public']
search_fields = ['name', 'location', 'notes', 'format']
ordering_fields = ['date', 'created_at']
def get_queryset(self):
return (
SpeedShootingSession.objects
.filter(user=self.request.user)
.select_related('rig', 'ammo', 'reloaded_batch__recipe', 'reloaded_batch__powder', 'analysis')
)
def get_serializer_class(self):
if self.action == 'list':
return SpeedShootingSessionListSerializer
if self.action in ('create', 'update', 'partial_update'):
return SpeedShootingSessionWriteSerializer
return SpeedShootingSessionDetailSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)