Reputation: 2595
I have the following model (simplified):
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
, then my custom DetailView based on generic.DetailView
:
class PostDetailView(generic.DetailView):
queryset = Post.objects.all()
and, finally, the following template:
{% 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 %}
My pagination implemented this way works, but due to the reverse ordering (i.e -date_created
) field, its Previous/Next labels are misplaced. In other words my template outputs "Previous" where it should be "Next", and vice versa. If I remove a -
sign in ordering = ('-date_created',)
it will work fine, but that's not the ordering I would like to have on my website.
Is there an easy and idiomatic way of fixing this misbehavior? What am I missing?
Upvotes: 1
Views: 147
Reputation: 1394
I think you have to use DetailView
with mixin
MultipleObjectMixin
like below...
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
Now, you should be able to use pagination method with post_page_obj
variable
Upvotes: -1
Reputation: 2595
I went this route and was able to solve the issue:
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
now in 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 %}
What do you think of this approach?
Upvotes: 0
Reputation: 7404
Add
ordering = ['-date_created']
or
ordering = Post._meta.ordering
to PostListView
Upvotes: 0