Django sees the pagination and the page shows switching to other pages. But when I go to another page, the comments are exactly the same as on other pages. On the home page, the pagination works fully.
In the terminal:
“GET /game_detail/dead-by-daylight/?page=1 HTTP/1.1” 200 28206
“GET /game_detail/dead-by-daylight/?page=3 HTTP/1.1” 200 28209
views.py
class GameDetail(LoginRequiredMixin, DataMixin, DetailView):
model = Game
context_object_name = 'game'
template_name = 'main/game_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
comments = Comment.objects.filter(game=self.object).select_related('author', 'game')
for comment in comments:
comment.str_value = comment.text
paginator = Paginator(comments, self.paginate_by)
page_number = self.request.GET.get('page')
page_obj = paginator.get_page(page_number)
context['page_obj'] = page_obj
context['comments'] = comments
context['game'] = self.object
context['average_rating'] = self.object.get_average_rating()
context['form'] = CommentForm
return context
utils.py
class DataMixin:
paginate_by = 3
comments_list.html
{% if page_obj %}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« First</a>
<a href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">Next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">Last »</a>
{% endif %}
</span>
</div>
{% endif %}
Hello there!
You haven’t shown your Comment
model, but I’m assuming that you don’t have a default ordering
on the Meta class, and it’s not explicitly calling order_by
on your queryset.
I found that this behavior of the Paginator
to be really misleading, it won’t fail if you pass an unordered queryset, just emit a warning. And passing a unordered queryset results in “inconsistent pages” that looks like the symptom that you’re describing.
leandrodesouzadev:
You haven’t shown your Comment
model, but I’m assuming that you don’t have a default ordering
on the Meta class, and it’s not explicitly calling order_by
on your queryset.
I found that this behavior of the Paginator
to be really misleading, it won’t fail if you pass an unordered queryset, just emit a warning. And passing a unordered queryset results in “inconsistent pages” that looks like the symptom that you’re describing.
I have order by. And i use MPTT in Comment model.
My model.
class Comment(MPTTModel):
game = models.ForeignKey(
Game, on_delete=models.CASCADE,
related_name='comments',
)
parent = TreeForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='children',
db_index=True,
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='comments_author',
db_index=True
)
text = models.TextField()
time_add = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
class MPTTMeta:
ordering_insertion_by = ['status']
SILVERHAND:
I have order by
I don’t see where are you applying an order_by
.
Can you please check this by adding this line on your view?
print("HAS ORDER BY ON QUERYSET", comments.ordered)
print() gives HAS ORDER BY ON QUERYSET True
Here order by:
ordering_insertion_by = ['status']
Or is it something else?
Sorry, i don’t know all details about MPTT model. But this is probably related to displaying comments from different tree levels based on the status?
That’s just a guess though, maybe other people can help you a bit more as i’m not experienced on MPTT
Problem solved.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
comments = Comment.objects.filter(game=self.object).select_related('author', 'game')
page = self.request.GET.get('page')
paginator = Paginator(comments, 15)
try:
comments = paginator.page(page)
except PageNotAnInteger:
comments = paginator.page(1)
except EmptyPage:
comments = paginator.page(paginator.num_pages)
user = self.request.user
user_rating = None
if user.is_authenticated:
user_rating = UserGameRating.objects.filter(profile=user.profile, game=self.object).first()
context['comments'] = comments
context['game'] = self.object
context['user_rating'] = user_rating
context['average_rating'] = self.object.get_average_rating()
context['form'] = CommentForm
return context