I've been working on a project of a blog where all posts are grouped by rubrics. The posts can be filtered by rubric in the frontend but I've got some problems whith implementing pagination. Paginator works fine and paginates filtered list, when I choose a rubric on my site it shows the number of pages and shows link to the next. But the url it forms ignores rubrication and instead of sending me to something like localhost/blog/?rubric=some_rubric&page=2 it shows localhost/blog/?page=2 The pagination works fine if I input adress by hand.
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from taggit.managers import TaggableManager
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset()\
.filter(status=Post.Status.PUBLISHED)
class Rubric(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
class Meta:
verbose_name_plural = 'Rubrics'
ordering = ('name',)
indexes = [models.Index(fields=['name']),]
def __str__(self):
return self.name
class Post(models.Model):
class Status(models.TextChoices):
DRAFT = 'DF', 'Draft'
PUBLISHED = 'PB', 'Published'
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
cover_img = models.ImageField(upload_to='post_covers/', blank=True, null=True)
rubric = models.ForeignKey(Rubric, on_delete=models.CASCADE, related_name='posts')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
excerpt = models.TextField(max_length=500)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=2, choices=Status.choices, default=Status.DRAFT)
objects = models.Manager() # The default manager.
published = PublishedManager() # Our custom manager.
tags = TaggableManager()
class Meta:
ordering = ['-publish']
indexes = [
models.Index(fields=['-publish']),
]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.publish.year,
self.publish.month,
self.publish.day,
self.slug])
view.py
from django.shortcuts import render
from .models import Post, Rubric
from django.utils import timezone
from django.views.generic.detail import DetailView
from django.core.paginator import Paginator
def post_list(request):
post_list = Post.published.all()
rubrics = Rubric.objects.all()
active_rubric = request.GET.get('rubric', '')
if active_rubric:
post_list = post_list.filter(rubric__slug=active_rubric)
paginator = Paginator(post_list, 3)
page_number = request.GET.get('page', 1)
posts = paginator.page(page_number)
context = {
'posts': posts,
'rubrics': rubrics,
'active_rubric': active_rubric,
}
return render(request, 'blog.html', context)
class PostDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["now"] = timezone.now()
return context
urls.py
from django.urls import path
from blog.views import post_list, PostDetailView
urlpatterns = [
path('', post_list, name='blog'),
path('<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
]
blog.html Here I insert pagination through include tag:
{% include 'pagination.html' with page=posts %}
pagination.html
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
{% if rubric.slug == active_rubric %}
<a href="?rubric={{ rubric.slug }}&page={{ page.previous_page_number }}">Previous</a>
{% else %}
<a href="?page={{ page.previous_page_number }}">Previous</a>
{% endif %}
{% endif %}
<span>
Page{{ page.number }} of {{ page.paginator.num_pages }}
</span>
{% if page.has_next %}
{% if rubric.slug == active_rubric %}
<a href="?rubric={{ rubric.slug }}&page={{ page.next_page_number }}">Next</a>
{% else %}
<a href="?page={{ page.next_page_number }}">Next</a>
{% endif %}
{% endif %}
</span>
</div>
I suspect that my pagination template cannot access rubric slug and active_rubric variables but I can't figure out how to make it see them.