Django why the pagination is not working? - django

Sorry because of the dumb question. I am reading a tutorial from book called build django 2 web application. and I get to the pagination topic but I can't get why it does not working even when I am copy-pasting carefully.
{% if is_paginated %}
<nav>
<ul class="pagination">
<li class="page-item">
First
</li>
{% if page_obj.has_previous %}
<li class="page-item">
{{page_obj.previous_page_number}}
</li>
{% endif %}
<li class="page-item active">
{{page_obj.number}}
</li>
{% if page_obj.has_next %}
<li class="page-item">
{{page_obj.next_page_number}}
</li>
{% endif %}
<li class="page-item">
Last
</li>
</ul>
</nav>
{% endif %}
#View
class MovieListView(ListView):
model = Movie
template_name = 'movie_list.html'

You haven't set the paginated_by attribute in the view class, so the contents won't be paginated.
class MovieListView(ListView):
model = Movie
template_name = 'movie_list.html'
paginate_by = 5

Related

Django Paginator shows post titles Not Page numbers, why?

i'm trying to use Django Paginator using ListView, but the paginator shows post title instead of page number:
Page number replaced with post title
how can i fix that?
this is my code:
in views.py:
from django.shortcuts import render
from django.core.paginator import Paginator
from django.views.generic import ListView, DetailView
from .models import Post
# Create your views here.
# PostObject_list by using ListView
class PostList(ListView):
model=Post
paginate_by=20
context_object_name='all_posts'
ordering=['-created_at']
# allpost by using ListView
'''class AllPost(ListView):
model=Post
context_object_name='allpost'
paginate_by=None
'''
# Post_singl_object using DetailView
class PostDetail(DetailView):
model=Post
in template post_list.html :
</div>
<nav aria-label="Page navigation example">
<ul class="pagination d-flex justify-content-center mt-1">
{% if all_posts.has_previous %}
<li class="page-item "><a class="page-link" href="?page={{ all_posts.previous_page_number }}">Previous</a></li>
{% endif %}
{% for page in all_posts %}
<li class="page-item ">
<a class="page-link" href="?page={{ page }}"><span>{{page}}</span></a>
</li>
{% endfor %}
{% if all_posts.has_next %}
<li class="page-item"><a class="page-link" href="?page={{all_posts.previous_page_number }}">Next</a></li>
{% endif %}
</ul>
</nav>
</div>
<!-- Pagination-->
thank you!
Using all_posts will not work because this is the object list, not the page object. all_posts will not have the page attributes like paginator, has_previous, previous_page_number, etc.
In this case you need to use page_obj, which is automatically added by ListView to the template context when paginating. You can get the page range from the template using page_obj.paginator.page_range:
{% for page in page_obj.paginator.page_range %}
<li class="page-item ">
<a class="page-link" href="?page={{ page }}"><span>{{ page }}</span></a>
</li>
{% endfor %}
The implementation for Previous and Next will also not work because of the same reason. To resolve that, you also need to use page_obj, so all in all:
{% if page_obj.has_previous %}
<li class="page-item "><a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a></li>
{% endif %}
{% for page in page_obj.paginator.page_range %}
<li class="page-item ">
<a class="page-link" href="?page={{ page }}"><span>{{ page }}</span></a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a></li>
{% endif %}
You should access to paginator. In your case, page_obj.paginator. Try to change your template to:
{% for i in page_obj.paginator.page_range %}
<li class="page-item ">
<a class="page-link" href="?page={{ page }}"><span>{{page}}</span></a>
</li>
{% endfor %}

blank page in pagination Django 3.1

I implemented the Django pagination to slice the results of the search on my site.
# views.py
def search(request):
# Keywords
if 'keywords' in request.GET:
keywords = request.GET['keywords']
if keywords:
title_list_control_valve = queryset_list.filter(title__icontains=keywords).order_by('title')
description_list_control_valve = queryset_list.filter(description__icontains=keywords).order_by('description').distinct('description')
result_list_control_valves = list(chain(title_list_control_valve,
description_list_control_valve))
result_list_control_valves_2 = list(dict.fromkeys(result_list_control_valves))
paginator = Paginator(result_list_control_valves_2, 1)
page = request.GET.get('page')
paged_queries = paginator.get_page(page)
context = {
'queries': paged_queries,
}
return render(request, 'pages/search.html', context)
else:
return render(request, 'pages/search.html')
else:
return render(request, 'pages/search.html')
the URL of the site when showing search results is :
http://localhost:8000/pages/search/?keywords=something
It works perfectly fine on the first page only. From the second page on, it shows an empty page, and the URL of the site changes to:
http://localhost:8000/pages/search/?page=2
I link to other pages in the HTML as following:
<div class="col-md-12">
{% if queries.has_other_pages %}
<ul class="pagination">
{% if queries.has_previous %}
<li class="page-item">
«
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">«</a>
</li>
{% endif %}
{% for i in queries.paginator.page_range %}
{% if queries.number == i %}
<li class="page-item active">
<a class="page-link">{{i}}</a>
</li>
{% else %}
<li class="page-item">
{{i}}
</li>
{% endif %}
{% endfor %}
{% if queries.has_next %}
<li class="page-item">
»
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">»</a>
</li>
{% endif %}
</ul>
{% endif %}
</div>
The ?keywords=something part of the URL goes away.
is it the problem?
how to make the other page's link work too?
Add keywords to your GET params. For ex. href="?page={{queries.previous_page_number}}&keywords={{request.GET.keywords}}"

pagination of a specific context in multiple context in ListView not working in django?

in django, i am trying to list some queries of several objects like user lists, categoies and Post list. the homepage will be contained couple of blocks or boxes. each box will have different query list like Post list, User List, category list. But only one context will have pagination and other won't and ofcourse the pagination will be working on Post list.
here is the views.py:
class BlogappListView(ListView):
model = Category,CustomUser
template_name = 'home.html'
context_object_name='category_list'
queryset=Category.objects.all()
paginate_by = 2
def get_context_data(self, **kwargs):
context = super(BlogappListView, self).get_context_data(**kwargs)
context['user_list']= CustomUser.objects.all()
context['post_list']=Post.objects.all()
activities=context['post_list']
return context
def get_related_activities(self,activities):
queryset=self.objects.activity_rel.all()
paginator=Paginator(queryset,2)
page=self.request.GET.get('page')
activities=paginator.get_page(page)
return(activities)
in urls.py:
urlpatterns = [
path('',BlogappListView.as_view(),name='home'),
]
in base.html, the paginate portion code:
<ul class="pagination justify-content-center mb-4">
{% if is_paginated %}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
</li>
{% endif %}
{% endif %}
</ul>
the main problem is that page number 1 is showing all the posts and also the second page. and category list is also truncated into 2 but the user list ok.
so how can i make it work ? is there any other way?
thank you in advance
i solved it. the revised code is:
class BlogappListView(ListView):
model = Category,CustomUser
template_name = 'home.html'
context_object_name='post_list'
queryset=Post.objects.all()
paginate_by=2
def get_context_data(self, **kwargs):
context = super(BlogappListView, self).get_context_data(**kwargs)
context['user_list']= CustomUser.objects.all()
context['category_list']=Category.objects.all()
return context
while looking for solution, i've got somewhere written that pagination will work only with queryset, not with the context. and that was so straight cut to understand and when i use paginate_by=2 in the queryset under Post it will only work for that.
the solution was quick and short but it took me a while to figure it out which is not good. but either way thanx to this platform to have this discussion and i am keeping this solution so that someone might get help from it.

Pagination using ListView and a dynamic/filtered queryset

I have a class based view that I am using to display a queryset in a table. I am also using a couple formsets to filter this queryset. I am using the get_queryset() method provided as part of the generic.ListView class to filter the diplayed results. Here is basically what my class looks like:
from django.views import generic
class UnifiedSingleSearch(generic.ListView):
template_name = 'app/foo.html'
model = MyModel
paginate_by = 30
def get_queryset(self):
if self.request.POST: # If we got here because of a search submission, filter
return MyModel.objects.filter('Some stuff base on the POST data')
return MyModel.objects.all() # Otherwise, just show everything
Because I am using a formset to submit multiple search criteria, I have to use a POST request. Upon initial submission of the form, the page reloads with a correctly filtered querset. However when I try to use my pagination controls, the POST request is thrown away and the page acts as if I am going to page#2 of MyModel.objects.all() instead of my filtered down subset.
How can I retain my filtered queryset when using pagination controls?
Here is the HTML for the pagination controls:
{% if is_paginated %}
<nav aria-label="Pagination nav">
<ul class="pagination">
{# Back a page #}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">❮</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❮</span>
</li>
{% endif %}
{# Page numbers #}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<span class="page-link">{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{# Next page #}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">❯</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">❯</span>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<p>No MyModel objects found</p>
{% endif %}
Switching to a GET request was the answer. Pagination controls also had to be edited a bit to retain the passed querystring. They should all include {{ request.GET.urlencode }} and then you tack on the page logic to the end like usual. Ends up looking something like this:
<li class="page-item">
<a class="page-link" href="?{{ request.GET.urlencode }}&page={{ page_obj.next_page_number }}">❯</a>
</li>

django request.user.is_superuser doesn't work

I want to show a button if the user is a superuser. I've found differents examples but my code doesn't work. The button doesn't appear. Anybody knows why?
views.py
def inici(request):
zones = Zona.objects.all()
return render_to_response('principal/inici.html', dict(zones=zones),
context_instance = RequestContext(request))
inici.html
{% if not user.is_authenticated %}
....
{% else %}
<ul>
<li class="nivell1">
Logout
</li>
<li class="nivell1">
<a class="nivell1" herf="#"> Configuració </a>
</li>
{% if request.user.is_superuser %}
<li class="nivell1">
Crear zona
</li>
{% endif %}
</ul>
{% endif %}
I only have a user in the database and he is a super user. I can see the "logout" button and the other one, but not the "crear zona" button.
You want this Generic view:
class IniciView(ListView):
template_name = 'principal/inici.html'
model = Zona
are the context processors in settings?
This is more redeable:
{% if user.is_authenticated %}
<ul>
<li class="nivell1">
Logout
</li>
<li class="nivell1">
<a class="nivell1" herf="#"> Configuració </a>
</li>
{% if user.is_superuser %}
<li class="nivell1">
Crear zona
</li>
{% endif %}
</ul>
{% else %}
...
{% endif %}
I've changed {% if request.user.is_superuser %} to {% if user.is_superuser %}