简体   繁体   English

在get_context_data中更改queryset后,分页不起作用

[英]Pagination does not work after changing queryset in get_context_data

Pagination works ok until I add reverse arg to QS for ordering queryset in reverse mode. 分页工作正常,直到我将reverse arg添加到QS以便以反向模式订购queryset为止。 After it pagination is broke. 分页之后。 I can use get() function and paginate it there, but I think that for this issue should be better solution. 我可以使用get()函数并在那里分页,但是我认为对于这个问题应该是更好的解决方案。 Thanks 谢谢

model.py: model.py:

class Log(models.Model):
    user = models.ForeignKey('auth.User')
    comment = models.CharField()
    date_add = models.DateTimeField()
    class Meta:
        ordering = ['-date_add']

view.py: view.py:

class LogView(ListView):
    model = UserLog
    template_name = 'log.html'
    context_object_name = 'log_list'
    paginate_by = 13

    def get_queryset(self):
        return Log.objects.filter(user=self.request.user).all()

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(LogView, self).get_context_data(**kwargs)
        if 'reverse' in self.request.GET:
            context['log_list'] = Log.objects.filter(user=self.request.user).all().order_by('date_add')
        return context

Move the code that runs the queryset to get_queryset , so that it runs before the queryset is paginated. 将运行queryset的代码移动到get_queryset ,以便在对查询集进行分页之前运行它。

def get_queryset(self):
    queryset = Log.objects.filter(user=self.request.user).all()
    if 'reverse' in self.request.GET:
        queryset = queryset.order_by('date_add')
    return queryset

The pagination is called in the get_context_data of the MultipleObjectMixin [GitHub] : 分页MultipleObjectMixin [GitHub]get_context_data调用:

 def get_context_data(self, *, object_list=None, **kwargs): """Get the context for this view.""" queryset = object_list if object_list is not None else self.object_list page_size = self.get_paginate_by(queryset) context_object_name = self.get_context_object_name(queryset) if page_size: paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size) context = { 'paginator': paginator, 'page_obj': page, 'is_paginated': is_paginated, 'object_list': queryset } else: context = { 'paginator': None, 'page_obj': None, 'is_paginated': False, 'object_list': queryset } if context_object_name is not None: context[context_object_name] = queryset context.update(kwargs) return super().get_context_data(**context) 

By overriding the element of the dictionary, you thus bypass this pagination. 通过覆盖字典的元素,您可以绕过此分页。

I think it is however better in this use-case to transfer the logic to the get_queryset method, in that case, you even do not have to override the get_context_data : 我想,但它是在这个用例更好的逻辑转移到get_queryset方法,在这种情况下,你甚至不必重写get_context_data

class LogView(ListView):
    model = UserLog
    template_name = 'log.html'
    context_object_name = 'log_list'
    paginate_by = 13

    def get_queryset(self):
        if 'reverse' in self.request.GET:
            return Log.objects.filter(user=self.request.user).all().order_by('date_add')
        else:
            return Log.objects.filter(user=self.request.user).all()

Note that the above has two potential problems: 请注意,上面有两个潜在的问题:

  1. you do not order the queryset in case 'reverse' is not in self.request.GET , which means that - unless you order in the model - there is no order, and hence pagination might go wrong over multiple pages; 如果'reverse' 不在 self.request.GET则不对查询集进行排序,这意味着-除非您在模型中进行排序-否则就没有顺序,因此分页可能会在多个页面上出错;
  2. since pagiantion uses already a page key in request.GET , this can result in some trouble in the links that change the GET parameter, since if you specify an url with ?page=3 , the reverse key will get dropped. 由于pagiantion已经在request.GET使用了page密钥,因此在更改GET参数的链接中可能会造成一些麻烦,因为如果使用?page=3指定url,则reverse键将被丢弃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM