You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django的paginate_queryset中设置自定义页码:获取用户所在页码并返回对应页面的实现问题

Returning the Page Containing the Current User in a Django REST Framework Scoreboard ViewSet

Looks like you’ve already nailed the core idea of calculating the user’s page, but there are two key fixes needed here: a bug in your page number calculation, and actually using that calculated page to return the right paginated data instead of the default page.

1. Fix the user_page Calculation

Your current logic counts users with lower XP than the current user, which gives an incorrect page number when using a descending XP sort (order_by('-xp_balance')).

Instead, you need to count users with higher XP than the current user—these are the users that appear before them in the scoreboard. The correct formula for the user’s page is:

# Count users with MORE XP than the current user
users_above = User.objects.filter(xp_balance__gt=request.user.xp_balance).count()
# Calculate page number: (number of users above // page size) + 1
user_page = (users_above // page_size) + 1

Let’s test this with an example:

  • Current user XP: 100
  • 3 users have higher XP, 2 have lower XP
  • Page size: 3
  • users_above = 3, so (3 // 3) +1 = 2—which is correct, since the user falls in the 2nd page (positions 4-6 in the sorted scoreboard).

2. Modify the View to Return the Correct Page

DRF’s default pagination pulls the page number from the page query parameter in the request. To return your calculated user_page instead, you can temporarily override the request’s query parameters to use this page number, then leverage DRF’s built-in pagination logic.

Here’s the updated get_user_page method that fixes both issues:

@action(url_path='user-page', methods=['get'], detail=False, url_name='user-page')
def get_user_page(self, request):
    # Get page size (use request param or default from pagination class)
    page_size = int(request.query_params.get('page_size')) if request.query_params.get('page_size') else self.pagination_class.page_size
    
    # Fix: Calculate users with higher XP to get the correct page number
    users_above = User.objects.filter(xp_balance__gt=request.user.xp_balance).count()
    user_page = (users_above // page_size) + 1
    
    # Create a copy of query params to modify (avoid mutating the original request)
    modified_query_params = request.query_params.copy()
    # Set the page parameter to our calculated user_page
    modified_query_params['page'] = str(user_page)
    modified_query_params['page_size'] = str(page_size)  # Ensure consistent page size
    
    # Update the request's query params to use our values
    request.query_params = modified_query_params
    
    # Use DRF's built-in pagination to fetch the correct page
    queryset = self.filter_queryset(self.get_queryset())
    page = self.paginate_queryset(queryset)
    
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        # Return paginated response with metadata (count, next/previous links)
        return self.get_paginated_response(serializer.data)
    
    # Fallback if pagination isn't applied (unlikely here, but safe to include)
    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

Key Changes Explained:

  • Fixed Page Logic: Now counts users with higher XP to accurately position the user in the sorted scoreboard.
  • Modified Query Params: We create a copy of the request’s query parameters to set the page value to our calculated user_page, ensuring DRF uses this page for pagination.
  • Consistent Response Format: Using self.get_paginated_response() returns standard pagination metadata (like total user count, next/previous page links) alongside the page data, matching the format of your other list endpoints.

Edge Cases to Keep in Mind

  • Tied XP Values: If other users have the same XP as the current user, you might want to adjust the users_above count to use xp_balance__gte instead of gt—this groups all users with equal XP on the same page, depending on your ranking rules.
  • Large Page Sizes: If the page size is bigger than the total number of users, user_page will default to 1, which is correct.

内容的提问来源于stack exchange,提问作者alighorbani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:47:42