Django ListView类视图实现登录用户数据分页时报错如何解决
问题根因
- 报错原因:Django ListView的执行逻辑是先完成查询集获取、分页切片,再执行
get_context_data传递上下文。你在get_context_data中拿到的context['foods']已经是按全量数据切好当前页的切片QuerySet,Django不允许对已经做过切片的QuerySet执行过滤操作,因此抛出对应错误。 - 显示所有用户数据的原因:分页逻辑执行时用的是未经过滤的全量
Food表数据,你在分页完成后才尝试过滤上下文里的数据集,不仅会报错,也无法改变分页阶段已经用了全量数据的事实。 - 你对
paginate_by的怀疑是误解:paginate_by完全可以和get_context_data搭配使用,你之前修改paginate_by的放置位置也没用,是因为它是类静态属性,定义位置不影响执行逻辑,核心问题是过滤操作的时机错了。
解决方案
你需要重写get_queryset方法,在分页逻辑执行前就完成用户数据过滤,get_context_data只用来传递额外的自定义上下文变量即可,修改后的代码如下:
class FoodList(LoginRequiredMixin, ListView): model = Food template_name = 'base/all_foods.html' context_object_name = 'foods' ordering = ['-created'] paginate_by = 20 def get_queryset(self): # 分页前先过滤出当前登录用户的专属数据 base_queryset = super().get_queryset() return base_queryset.filter(user=self.request.user) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 额外自定义变量正常在这里加即可 context['color'] = 'red' return context
get_queryset是ListView专门用来获取基础查询集的方法,会在分页逻辑执行前调用,过滤后的查询集会直接用来做分页计算、切分当前页数据,完全符合你只展示当前用户数据、每页20条的需求。
内容的提问来源于stack exchange,提问作者Sana
相关产品推荐
相关产品推荐

