fixed pagination

This commit is contained in:
afanasyev.aa 2025-07-07 23:15:29 +09:00
parent 80ffab27e9
commit dd99c395a0
4 changed files with 51 additions and 15 deletions

17
api/custom_pagination.py Normal file
View file

@ -0,0 +1,17 @@
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.response import Response
class CustomLimitOffsetPagination(LimitOffsetPagination):
limit_query_param = 'limit'
offset_query_param = 'skip'
max_limit = 100
default_limit = 10
def get_paginated_response(self, data):
return Response({
'total': self.count,
'limit': self.limit,
'skip': self.offset,
'predictions': data
})

View file

@ -4,7 +4,8 @@ import json
from rest_framework import status, generics, permissions from rest_framework import status, generics, permissions
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, ViewSet from rest_framework.viewsets import ModelViewSet, ViewSet, GenericViewSet
from rest_framework.exceptions import APIException
from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
from rest_framework.decorators import api_view, permission_classes, authentication_classes, action from rest_framework.decorators import api_view, permission_classes, authentication_classes, action
@ -14,14 +15,15 @@ from django.utils.decorators import method_decorator
from django.http import JsonResponse from django.http import JsonResponse
from django.contrib.auth import authenticate, login, logout, get_user_model from django.contrib.auth import authenticate, login, logout, get_user_model
from django.middleware.csrf import get_token from django.middleware.csrf import get_token
from django.core.exceptions import ValidationError
from django.utils.dateparse import parse_datetime from django.utils.dateparse import parse_datetime
from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate, TelemetryPacket from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate, TelemetryPacket
from .serializers import PredictionSerializer, TelemetryPacketSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer from .serializers import PredictionSerializer, TelemetryPacketSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer
from .services.tawhiri import TawhiriClient from .services.tawhiri import TawhiriClient
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
from .permissions import ReadOnlyOrAuthenticated, IsOwner from .permissions import ReadOnlyOrAuthenticated, IsOwner
from .custom_pagination import CustomLimitOffsetPagination
from datetime import datetime
User = get_user_model() User = get_user_model()
@ -37,8 +39,13 @@ def get_prediction_from_tawhiri(params):
f"Tawhiri error: {response.status_code} {response.text}") f"Tawhiri error: {response.status_code} {response.text}")
class PredictionViewSet(ViewSet): class PredictionViewSet(GenericViewSet):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
pagination_class = CustomLimitOffsetPagination
def list(self, request):
queryset = Prediction.objects.filter(user=request.user)
return Response(PredictionSerializer(queryset, many=True).data)
def create(self, request): def create(self, request):
serializer = PredictionRequestSerializer(data=request.data) serializer = PredictionRequestSerializer(data=request.data)
@ -92,7 +99,16 @@ class PredictionViewSet(ViewSet):
filters['satellite_id'] = satellite_id filters['satellite_id'] = satellite_id
queryset = Prediction.objects.filter(**filters) queryset = Prediction.objects.filter(**filters)
return Response(PredictionSerializer(queryset, many=True).data) queryset = self.filter_queryset(queryset)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = PredictionSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = PredictionSerializer(queryset, many=True)
return Response(serializer.data)
@action(detail=False, methods=["get"]) @action(detail=False, methods=["get"])
def history(self, request): def history(self, request):
@ -168,6 +184,7 @@ class WhoAmIView(APIView):
@extend_schema(methods=["GET"], description="Get CSRF token") @extend_schema(methods=["GET"], description="Get CSRF token")
@csrf_exempt
@api_view(["GET"]) @api_view(["GET"])
@permission_classes([AllowAny]) @permission_classes([AllowAny])
def get_csrf(request): def get_csrf(request):
@ -219,6 +236,7 @@ class SavedPointViewset(ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(user=self.request.user) serializer.save(user=self.request.user)
class PreditctionTemplateViewset(ModelViewSet): class PreditctionTemplateViewset(ModelViewSet):
permission_classes = [IsOwner] permission_classes = [IsOwner]
serializer_class = PreditctionTemplateSerializer serializer_class = PreditctionTemplateSerializer

View file

@ -105,6 +105,13 @@ WSGI_APPLICATION = 'testapi.wsgi.application'
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases # https://docs.djangoproject.com/en/5.1/ref/settings/#databases
if PRODUCTION: if PRODUCTION:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
else:
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.postgresql',
@ -115,13 +122,7 @@ if PRODUCTION:
'PORT': os.getenv('DB_PORT'), 'PORT': os.getenv('DB_PORT'),
} }
} }
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation # Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
@ -187,10 +188,10 @@ REST_FRAMEWORK = {
} }
CSRF_COOKIE_SAMESITE = 'None' # temp CSRF_COOKIE_SAMESITE = 'Lax' # temp
CSRF_COOKIE_SECURE = False CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SAMESITE = 'None' # temp SESSION_COOKIE_SAMESITE = 'Lax' # temp
SESSION_COOKIE_SECURE = False SESSION_COOKIE_SECURE = False
CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:5173').split(',') CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:5173, http://localhost:8000').split(',')