144 lines
6.0 KiB
Python
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)
|