keywrod library sorting issue and fitlers inclusion, adn PLAN for refactor of whole page realted

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-18 16:54:07 +00:00
parent 6c69ca3feb
commit 9e88c475f7
4 changed files with 895 additions and 3 deletions

View File

@@ -47,3 +47,19 @@ class CustomPageNumberPagination(PageNumberPagination):
return Response(response_data)
class LargeTablePagination(CustomPageNumberPagination):
"""
Pagination class for large reference tables (e.g., SeedKeywords).
Default page size: 25
Max page size: 500
Important: Server-side sorting/filtering is applied to ALL records first,
then only the requested page is returned. This ensures:
- Sorting by volume returns the 500 highest/lowest volume records globally
- Filters apply to all records, not just the visible page
- Pagination shows accurate total counts
"""
page_size = 25
max_page_size = 500

View File

@@ -15,7 +15,7 @@ from igny8_core.api.base import AccountModelViewSet
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
from igny8_core.api.response import success_response, error_response
from igny8_core.api.throttles import DebugScopedRateThrottle
from igny8_core.api.pagination import CustomPageNumberPagination
from igny8_core.api.pagination import CustomPageNumberPagination, LargeTablePagination
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess
from .models import User, Account, Plan, Subscription, Site, Sector, SiteUserAccess, Industry, IndustrySector, SeedKeyword
from .serializers import (
@@ -827,11 +827,15 @@ class SeedKeywordViewSet(viewsets.ReadOnlyModelViewSet):
"""
ViewSet for SeedKeyword - Global reference data (read-only for non-admins).
Unified API Standard v1.0 compliant
Sorting and filtering is applied server-side to ALL records, then paginated.
This ensures operations like "sort by volume DESC" return the globally highest
volume keywords, not just the highest within the current page.
"""
queryset = SeedKeyword.objects.filter(is_active=True).select_related('industry', 'sector')
serializer_class = SeedKeywordSerializer
permission_classes = [permissions.AllowAny] # Read-only, allow any authenticated user
pagination_class = CustomPageNumberPagination
pagination_class = LargeTablePagination # Supports up to 500 records per page
throttle_scope = 'auth'
throttle_classes = [DebugScopedRateThrottle]
@@ -855,12 +859,14 @@ class SeedKeywordViewSet(viewsets.ReadOnlyModelViewSet):
)
def get_queryset(self):
"""Filter by industry and sector if provided."""
"""Filter by industry, sector, and difficulty range if provided."""
queryset = super().get_queryset()
industry_id = self.request.query_params.get('industry_id')
industry_name = self.request.query_params.get('industry_name')
sector_id = self.request.query_params.get('sector_id')
sector_name = self.request.query_params.get('sector_name')
difficulty_min = self.request.query_params.get('difficulty_min')
difficulty_max = self.request.query_params.get('difficulty_max')
if industry_id:
queryset = queryset.filter(industry_id=industry_id)
@@ -871,6 +877,18 @@ class SeedKeywordViewSet(viewsets.ReadOnlyModelViewSet):
if sector_name:
queryset = queryset.filter(sector__name__icontains=sector_name)
# Difficulty range filtering
if difficulty_min is not None:
try:
queryset = queryset.filter(difficulty__gte=int(difficulty_min))
except (ValueError, TypeError):
pass
if difficulty_max is not None:
try:
queryset = queryset.filter(difficulty__lte=int(difficulty_max))
except (ValueError, TypeError):
pass
return queryset
@action(detail=False, methods=['get'], url_path='stats', url_name='stats')