DRF获取count值最高的2条Product记录问题求助
Fixing the Top Viewed Products API in DRF
Hey there! Let's fix your code step by step. The main issue with your original approach is that aggregate(Max('count')) only returns the highest count value (as a dictionary like {'count__max': X}), not the product IDs associated with the top view counts. Here's the corrected implementation:
Corrected View Code
from django.db.models import Case, When from rest_framework.views import APIView from rest_framework.response import Response from .models import Product, ProductViewCount from .serializers import ProductSerializer # Ensure this is imported correctly class ViewTopLiked(APIView): def get(self, request): # Get top 2 ProductViewCount records ordered by highest count first top_view_entries = ProductViewCount.objects.order_by('-count')[:2] # Extract product IDs in the order of highest view count prod_ids = list(top_view_entries.values_list('product', flat=True)) # Fetch Product records while preserving the view count ranking order if prod_ids: # Use Case/When to maintain the order of our prod_ids list ordering = Case(*[When(product_id=prod_id, then=index) for index, prod_id in enumerate(prod_ids)]) products = Product.objects.filter(product_id__in=prod_ids).order_by(ordering) else: # Handle empty ProductViewCount scenario gracefully products = Product.objects.none() # Serialize and return the response serializer = ProductSerializer(instance=products, many=True, context={'request': request}) return Response(serializer.data)
Key Changes Explained
Replacing
aggregatewith ordered queryset:- Instead of
aggregate(Max('count')), we useProductViewCount.objects.order_by('-count')[:2]to fetch the top 2 records with the highest view counts, sorted in descending order.
- Instead of
Extracting product IDs:
values_list('product', flat=True)on the ordered queryset gives us a flat list of associated product IDs. Converting to a list ensures we keep the ranking order for the next step.
Preserving ranking order in Product results:
- Django's default
filter(product_id__in=...)doesn't maintain the input list order. UsingCaseandWhenensures products are returned in the same order as their view count ranking (most viewed first).
- Django's default
Edge case handling:
- We added a check for empty
prod_idsto avoid errors when there are no records inProductViewCount.
- We added a check for empty
Additional Notes
- If multiple products have the same highest count, the queryset will take the first two entries based on Django's default ordering (primary key). To add a tiebreaker (e.g., newest products first), adjust the
order_byclause:top_view_entries = ProductViewCount.objects.order_by('-count', '-product__created_date')[:2] - Double-check that your
ProductSerializerincludes all the fields you need from theProductmodel.
内容的提问来源于stack exchange,提问作者devmrh
相关产品推荐
相关产品推荐

