I am currently facing this problem with Django ListView. Basically, I need to filter some questions per topic and I would like to paginate the results. My code is working perfectly about the queryset part (the results are showed correctly) but I am facing a problem with pagination. Let's say I have so far 8 items in my query, if I choose to paginate_by = 10, it shows me just one page. If, otherwise, I choose to paginate by, let's say, 3, it shows me 3 pages to choose in the template (which is correct) but it shows me ALL the results of the query in my page. I post some code to be more clear
models.py:
class Tag(models.Model):
name = models.CharField(max_length=300, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def clean(self):
self.name = self.name.capitalize()
def __str__(self):
return self.name
class Question(models.Model):
post_owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=5000, default='')
body = tinymce_models.HTMLField()
tags = models.ManyToManyField(
Tag, related_name='tags')
viewers = models.ManyToManyField(
User, related_name='viewed_posts', blank=True)
views.py:
class TagQuestionsListView(ListView):
template_name = 'main/tag_questions.html'
paginate_by = 20
def get_queryset(self, **kwargs):
tag = Tag.objects.get(name=self.kwargs['name'])
questions = Question.objects.filter(tags=tag)
return questions
def get_contextdata(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tag'] = Tag.objects.get(name=self.kwargs['name'])
context['questions'] = Question.objects.filter(
tags=context['tag'], is_deleted=False)
return context
template:
{% extends 'base.html' %}
{% load humanize %}
{% block title %}Domande su {{tag.name}}{% endblock title %}
{% block content %}
<style>
.text {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* number of lines to show */
line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
<div >
<div >
<h3 style="display: inline;">Ultime {{ questions.count }} Domande</h3>
{% if request.user.is_authenticated %}
<a href="{% url 'main:new_question' %}" style="display: inline;">Fai una domanda</a>
{% else %}
<a href="{% url 'account:login_user' %}" style="display: inline;">Fai una domanda</a>
{% endif %}
</div>
<h5 >{{ total_questions.count }} domande totali </h5>
<hr>
{% for question in questions %}
<div >
<div >
<p>{{ question.count_all_the_votes }} Voti</p>
<p>{{ question.count_answers }} Risposte</p>
<p>{{ question.calculate_viewers }} Visualizzazioni</p>
</div>
<div >
<a href="{% url 'main:question_details' pk=question.id slug=question.slug %}"><h5>{{question.title}}</h5></a>
<div >
{{ question.body|striptags }}
</div>
{% for tag in question.tags.all %}
<a href="{% url 'main:tag_questions' name=tag.name %}">{{tag.name}}</a>
{% endfor %}
<div >
<a style="display: inline;" href="">{{question.post_owner}}</a>
{% if question.is_edited == False %}
<span style="display:inline;">creata {{question.created_at | naturaltime}}</span>
{% else %}
<span style="display:inline;"> modificata {{question.edited_time | naturaltime}} da <a style="display: inline;" href="">{{question.edited_by.username}}</a></span>
{% endif %}
</div>
</div>
</div>
<hr>
{% endfor %}
</div>
<div >
<div >
<div >
<div >
<nav aria-label="Page navigation example">
<ul >
{% if page_obj.has_previous %}
<li ><a href="{% url 'main:tag_questions' name=tag.name %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.previous_page_number }}">Precedente</a></li>
{% else %}
<li ><a href="#">Precedente</a></li>
{% endif %}
{% for i in paginator.page_range %}
<li ><a href="?filter={{ filter }}&orderby={{ orderby }}&page={{ i }}">{{i}}</a></li>
{% endfor %}
{% if page_obj.has_next %}
<li ><a href="{% url 'main:tag_questions' name=tag.name %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.next_page_number }}">Prossima</a></li>
{% else %}
<li ><a href="#">Prossima</a></li>
{% endif %}
</ul>
</nav>
</div>
</div>
</div>
{% endblock content %}
CodePudding user response:
With this I want my comment converter to answer.
You have to use page_obj
instead questions
in your template.
<--! ⬇️⬇️⬇️ -->
{% for question in page_obj %}
<div >
<div >
<p>{{ question.count_all_the_votes }} Voti</p>
<p>{{ question.count_answers }} Risposte</p>
<p>{{ question.calculate_viewers }} Visualizzazioni</p>
</div>
<div >
<a href="{% url 'main:question_details' pk=question.id slug=question.slug %}"><h5>{{question.title}}</h5></a>
<div >
{{ question.body|striptags }}
</div>
{% for tag in question.tags.all %}
<a href="{% url 'main:tag_questions' name=tag.name %}">{{tag.name}}</a>
{% endfor %}
<div >
<a style="display: inline;" href="">{{question.post_owner}}</a>
{% if question.is_edited == False %}
<span style="display:inline;">creata {{question.created_at | naturaltime}}</span>
{% else %}
<span style="display:inline;"> modificata {{question.edited_time | naturaltime}} da <a style="display: inline;" href="">{{question.edited_by.username}}</a></span>
{% endif %}
</div>
</div>
</div>
<hr>
{% endfor %}
So, if you define attribute paginate_by
, than ListView
(django docs) adds a paginator
and page_obj
to the context
. To allow the users to navigate between pages, add links to the next and previous page, in your template.