Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@
# for enabling swagger
REST_FRAMEWORK = {
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PAGINATION_CLASS": 'data.pagination.Pagination',
"PAGE_SIZE": 20,
"DEFAULT_AUTHENTICATION_CLASSES": [
# "rest_framework.authentication.BasicAuthentication",
# "rest_framework.authentication.SessionAuthentication",
Expand Down
33 changes: 33 additions & 0 deletions app/data/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class Pagination(PageNumberPagination):
"""Species Pagination"""
page_query_param = 'page'
page_size = 20

def paginate_queryset(self, queryset, request, view=None):
page_param = request.query_params.get(self.page_query_param, '1')

if '-' in page_param:
try:
start, end = map(int, page_param.split('-'))
if start < 1 or end < start:
return []
start_index = (start - 1) * self.page_size
end_index = end * self.page_size
self.page = queryset[start_index:end_index] # ✅ FIXED
return self.page
except ValueError:
return []
else:
return super().paginate_queryset(queryset, request, view)

def get_paginated_response(self, data):
if hasattr(self, 'page') and self.page is not None:
return super().get_paginated_response(data)
else:
return Response({
"count": len(data),
"results": data
})
36 changes: 35 additions & 1 deletion app/data/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
from django.conf import settings
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.parsers import MultiPartParser
from data.pagination import Pagination
from rest_framework.response import Response


from_email = settings.EMAIL_HOST_USER
Expand Down Expand Up @@ -290,8 +292,40 @@ class SpeciesViewSet(BaseApprovalViewSet):
serializer_class = serializers.SpeciesSerializer
queryset = Species.objects.all()
authentication_classes = [JWTAuthentication]
pagination_class = Pagination
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ("status", "uploaded_by", "selfies", "smiles")

def list(self, request, *args, **kwargs):
"""Custom list to support page ranges like 1-3."""
page_param = request.query_params.get("page", "1")
page_size = self.pagination_class.page_size or 20 # Default to 20

try:
if "-" in page_param:
start, end = map(int, page_param.split("-"))
if start > end or start < 1:
raise ValueError("Invalid range")
start_index = (start - 1) * page_size
end_index = end * page_size
else:
page = int(page_param)
start_index = (page - 1) * page_size
end_index = page * page_size
except Exception:
return Response({"error": "Invalid page format. Use ?page=2 or ?page=1-3"}, status=400)

# Apply filters manually using DRF's get_queryset()
qs = self.filter_queryset(self.get_queryset())
total_count = qs.count()
sliced = qs[start_index:end_index]
serializer = self.get_serializer(sliced, many=True)

return Response({
"count": total_count,
"results": serializer.data,
"range": f"{start_index + 1}–{min(end_index, total_count)}"
})

def get_permissions(self):
"""No authentication required for GET requests."""
Expand Down Expand Up @@ -1139,4 +1173,4 @@ def get(self, request, user_id: int, format=None):
"pending": total_length_pending, # Changed key name
"unapproved_counts": list(unapproved_counts),
}
)
)