【问题标题】:Django pagination dependent on orderingDjango分页依赖于排序
【发布时间】:2020-02-19 01:13:17
【问题描述】:

我有以下模型(简化):

class Post(models.Model):
    title = models.CharField(max_length=20)
    date_created = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('-date_created',) # note the "reverse" ordering here

,然后是我基于generic.DetailView的自定义DetailView:

class PostDetailView(generic.DetailView):
    queryset = Post.objects.all()

最后是以下模板:

{% with object.get_previous_by_date_created as prev %}
    {% if prev %}
    <a class="nav-link-prev"
       href="{% url "blog:post_detail" pk=prev.id %}">Previous</a>
    {% endif %}
{% endwith %}

{% with object.get_next_by_date_created as next %}
    {% if next %}
    <a class="nav-link-next"
       href="{% url "blog:post_detail" pk=next.id %}">Next</a>
    {% endif %}
{% endwith %}

我以这种方式实现的分页工作,但由于反向排序(即-date_created)字段,其上一个/下一个标签放错了位置。换句话说,我的模板输出“上一个”应该是“下一个”,反之亦然。如果我删除 - 登录 ordering = ('-date_created',) 它将正常工作,但这不是我希望在我的网站上的顺序。

是否有一种简单而惯用的方法来解决这种不当行为?我错过了什么?

【问题讨论】:

  • 所以只更改了标签(下一个 | 上一个),否则可以正常工作?
  • @HoratiuJeflea 所有链接 HTML。
  • 您能否将order_by 添加到您的queryset 中,例如queryset = Post.objects.all().order_by('-date_created') 并检查您的输出。
  • @MKPatel 尝试了您的方法。我没有看到任何变化。
  • 作为 hack,我可能会使用 {% with object.get_next_by_date_created as prev %}{% with object.get_previous_by_date_created as next %} 但它很难看。

标签: django pagination


【解决方案1】:

添加

ordering = ['-date_created']

ordering = Post._meta.ordering

PostListView

【讨论】:

  • 我的问题与generic.DetailView有关,而不是generic.ListView,我更新了。很抱歉造成混乱。
【解决方案2】:

我走这条路并且能够解决问题:

class PostDetailView(generic.DetailView):
    model = Post

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)

        next = Post.objects.filter(pk__lt=self.object.pk).order_by('-pk')[:1]
        prev = Post.objects.filter(pk__gt=self.object.pk).order_by('pk')[:1]
        if prev:
            context['prev'] = prev[0]
        if next:
            context['next'] = next[0]

        return context

现在在 template.html 中:

{% if prev %}
<a class="nav-link-prev"
   href="{% url "post_detail" pk=prev.id %}">Previous
</a>
{% endif %}

{% if next %}
    <a class="nav-link-next"
       href="{% url "post_detail" pk=next.id %}">Next
    </a>
{% endif %}

您如何看待这种方法?

【讨论】:

  • 是的,逻辑上你是写的,但是如果 Django 提供了使用 prev/next 的内置功能,那么为什么我们应该编写我们的逻辑来应用相同的功能。 :)
  • 不,从逻辑上讲它们是不一样的。遗憾的是,我还没有看到“内置”功能。
【解决方案3】:

我认为你必须使用 DetailViewmixin MultipleObjectMixin 如下...

from django.views.generic.detail import DetailView
from django.views.generic.list import MultipleObjectMixin
from django.core import paginator

class PostDetailView(DetailView, MultipleObjectMixin):
    model = Post
    paginate_by = 5

    def get_context_data(self, **kwargs):
        object_list = Post.objects.all().order_by('-date_created')
        context = super(PostDetailView, self).get_context_data(object_list=object_list, **kwargs)
        post_paginator = paginator.Paginator(object_list, self.paginate_by)
        # Catch invalid page numbers
        try:
            post_page_obj = post_paginator.page(purchases_page)
        except (paginator.PageNotAnInteger, paginator.EmptyPage):
            post_page_obj = post_paginator.page(1)

        context["post_page_obj"] = post_page_obj
        return context

现在,您应该可以使用带有post_page_obj 变量的分页方法了

【讨论】:

  • 谢谢,它成功了。顺便说一句,它也可以在您的代码 sn-p 中没有 paginate_by = 5 的情况下工作。你能解释一下原因吗?
  • 是的,因为如果不写paginate_by,它将采用默认分页。
  • 我仍然不确定它是否适用于我在问题中发布的“默认”模板代码。
  • 但是你编辑之前的模板代码很容易理解和使用。
  • Django 文档中paginate_by 的引用docs.djangoproject.com/en/3.0/ref/class-based-views/…
猜你喜欢
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 2011-10-02
  • 2014-12-31
  • 1970-01-01
  • 2023-04-06
相关资源
最近更新 更多