Django Pagination "Page not found" - python

I'm currently having issues with my Django pagination. I have a query set of 9 objects and am paginating one object to a page. So I should have 9 pages total.
Paginator is showing that I have 9 pages, but when I click the "next" page button my (Always on the last/last two pages) my url turns to: http://127.0.0.1:8000/forum/1?page=7
Then I get a 404 page not found error along with "Invalid page (7): That page contains no results"
Here is my class code:
class DirectoryClass(generic.ListView):
template_name = "forum_directory.html"
model = Directory
paginate_by = 1
def get_context_data(self, **kwargs):
context = super(DirectoryClass, self).get_context_data(**kwargs)
directory = Directory.objects.filter(pk=self.kwargs['directory_id'])
context['page'] = 'forum'
context['name'] = directory.first().name
context['user'] = self.request.user
topic_set = directory.first().topic_set.all().order_by('-last_post')
print(topic_set.all())
paginator = Paginator(topic_set, self.paginate_by)
page = self.request.GET.get('page')
try:
topic_set = paginator.page(page)
except PageNotAnInteger:
topic_set = paginator.page(1)
except EmptyPage:
topic_set = paginator.page(paginator.num_pages)
context['topics'] = topic_set
context['page'] = page
return context
Here is the HTML used to change the page:
<div style="width: 1240px; margin: auto; text-align: right;">
{% if topics.has_other_pages %}
<ul class="pagination forum-pagination">
{% if topics.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in topics.paginator.page_range %}
{% if topics.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if topics.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
Here is the url
path(r'/<int:directory_id>',views.DirectoryClass.as_view(), name='forum_directory'),
What am I doing wrong here?

def get_context_data(self, **kwargs):
context = super(DirectoryClass, self).get_context_data(**kwargs)
context['page'] = 'forum'
context['user'] = self.request.user
return context
def get_queryset(self):
directory = Directory.objects.filter(pk=self.kwargs['directory_id'])
topics = directory.first().topic_set.all().order_by('-last_post')
return topics
use this only in your ListView, as Django provides pagination to all the Class Based View

Related

Django-filter pagination only the first search filed failed

I'm using django-filter with pagination, as long as the search filed is in the first place in filter.py -> fields = ['name_procss','typeLevel'] list, the pagination for filter of that filed will not work.
fitler.py:
import django_filters
from MyCore.models import MyRunStats
class MyRunStatsFilter(django_filters.FilterSet):
def gen_choice(self,filed):
return tuple((l, l) for l in list(MyRunStats.objects.exclude(**{filed: None}).values_list(filed, flat=True).distinct()))
name_procss = django_filters.ChoiceFilter(label='Process',choices=tuple,null_label='None',null_value='null')
typeLevel = django_filters.ChoiceFilter(label='Message Type',choices=tuple,null_label='None',null_value='null')
class Meta:
model = MyRunStats
fields = ['name_procss','typeLevel']
def __init__(self, *args, **kwargs):
super(MyRunStatsFilter, self).__init__(*args, **kwargs)
self.filters['name_procss'].extra['choices'] = self.gen_choice('name_procss')
self.filters['typeLevel'].extra['choices'] = self.gen_choice('typeLevel')
Views.py
def runstat_hist_view_render(request):
all_obj = MyRunStats.objects.all().order_by('-create_dttm')
hist_filter = MyRunStatsFilter(request.GET, queryset=all_obj)
paginator= Paginator(hist_filter.qs[:57], 20)
page = request.GET.get('page')
try:
response = paginator.page(page)
except PageNotAnInteger:
response = paginator.page(1)
except EmptyPage:
response = paginator.page(paginator.num_pages)
context = {'response': response,'filter': hist_filter}
return render(request, 'My/My_runstat_hist.html',context)
html:
<form method="get" >
{{ filter.form}}
<button type="button" onclick="submitFilter()" id="hist-search-button" >Search Message</button>
</form>
{% for item in response %}
<nav>
<ul class="pagination">
{% if response.has_previous %}
<li>« First</li>
<li >Previous</li>
{% else %}
<li>Previous</li>
{% endif %}
{% for num in response.paginator.page_range %}
{% if response.number == num %}
<li>{{num}}</li>
{% elif num > response.number|add:'-3' and num < response.number|add:'3' %}
<li>{{num}}</li>
{% endif %}
{% endfor %}
{% if response.has_next %}
<li>Next</li>
<li>Last »</li>
{% else %}
<li>Next</li>
{% endif %}
</ul>
</nav>
The issue is ,no matter which item is in the first place in filter.py->fields = ['name_procss','typeLevel'],for example now the 'name_procss' is in the first place ,then the pagination for 'name_procss' not work,if I put 'typeLevel' in the first place ,then pagination for 'typeLevel' will not work but for 'name_procss' will work.

Adding a maximum limit to the number of post using python

I need to limit the number of posts in Django queries. I have tried to add a min and max but nothing seemed to have worked. I have added home.html into the code.
Example: I should only have the 15 most recent posts in my blog. The rest can be seen by clicking on the category button.
Home.html:
{% extends 'base.html' %}
{% block content %}
<h1>Posts</h1>
<ul>
{% for post in object_list %}
<li>{{post.title}}
<style>
a {
text-transform: capitalize;
}
</style>
- {{ post.category }} - <a href="{% url 'show_profile_page' post.author.profile.id %}">{{ post.author.first_name }}
{{ post.author.last_name }}</a> - {{ post.post_date }} <small>
{% if user.is_authenticated %}
{% if user.id == post.author.id %}
- (Edit)
(Delete)
{% elif user.id == 1 %}
- (Edit)
(Delete)
{% endif %}
{% endif %}
</small><br/>
{{ post.snippet }}</li>
{% endfor %}
</ul>
{% endblock %}
view.py:
class HomeView(ListView):
model = Post
template_name = 'home.html'
ordering = ['-id']
def get_context_data(self, *args, **kwargs):
cat_menu = Category.objects.all()
context = super(HomeView, self).get_context_data(*args,**kwargs)
context["cat_menu"] = cat_menu
return context
models.py:
class Post(models.Model):
title = models.CharField(max_length=255)
header_image = models.ImageField(null=True, blank=True, upload_to='images/')
title_tag = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = RichTextField(blank=True, null=True)
post_date = models.DateField(auto_now_add=True)
category = models.CharField(max_length=255, default='intro')
snippet = models.CharField(max_length=255)
likes = models.ManyToManyField(User, related_name='post_likes')
dislikes = models.ManyToManyField(User, related_name='post_dislikes')
I think you have another template for displaying categorised objects when you click category button. As you said
"I should only have the 15 most recent posts in my blog. The rest can
be seen by clicking on the category button."
In this case you can use a simple hack to display most recent posts from your table.
query all objects in descending order in views
all_objs = Post.objects.all().order_by('-id')
Then use {% if forloop.counter <= 15 %} to display last 15 items only. as follow.
templates
{% for post in object_list %}
{% if forloop.counter <= 15 %}
<h4>{{obj}} #or anything really that is meant to be shown on the home page.</h4>
{% endif %}
{% endfor %}
You can do something like this:
def get_context_data(self, *args, **kwargs):
context = super(HomeView, self).get_context_data(*args,**kwargs)
context["cat_menu"] = Category.objects.all()
context["most_recent_posts"] = Post.objects.filter(author=self.request.user).order_by('-post_date')[:15]
return context
This will get the 15 most recent posts authored by the current user, ordered by the date it was posted.
Then just handle displaying this in home.html for example:
<ul>
{% for p in most_recent_posts %}
<li>{{ p.title }}</li>
{% endfor %}
</ul>
Just limit your query to the latest 15 entries sorted by post_date:
cat_menu = Category.objects.latest("post_date")[:15]
https://docs.djangoproject.com/en/3.2/topics/pagination/
The best way is Django Pagintion.
{% for contact in page_obj %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br>
...
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
from django.core.paginator import Paginator
from django.shortcuts import render
from myapp.models import Contact
def listing(request):
contact_list = Contact.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page.
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'list.html', {'page_obj': page_obj})
you can use Django pagination api . Manage your data through page number. Initially pass 1 and after that page number given by pagination.
paginator = Paginator(yourquerysetdata, 20)
page_num = request.data.get('page')
result = yourSerializerName(paginator.get_page(page_num) many=True).data
try:
page = paginator.page(page_num)
except:
page = paginator.page(1)
count = paginator.num_pages
resultobj = paginator.get_page(page_num)
has_prev = resultobj.has_previous()
has_next = resultobj.has_next()
page_range = resultobj.paginator.page_range.stop - 1
if has_prev:
prev_page_no = resultobj.previous_page_number()
else:
prev_page_no = 0
if has_next:
next_page_no = resultobj.next_page_number()
else:
next_page_no = None
context = dict()
context['page'] = page.number
context['page_no'] = count
It is very simple. You just have to modify the query that you are using to fetch the posts.
In the get_context_data() method, replace cat_menu = Category.objects.all() with cat_menu = Category.objects.all().order_by('-post_date')[:15]. This will limit the number of results to 15 most recent objects.
For more understanding, you can take a look at the official Django docs for Limiting QuerySets.

Search Bar in Django?

I have a bootstrap search bar and I want it to search for a list of all tags in a database. Tags are a like a facebook page or reddit tags.
When I submit my search, I want the URL to include the GET-parameter: ?q="typeword", but the application has to redirect to a new page, and preserve the tags parameter while doing so. How can I do this?
I have tried using GET-request and paginator, but nothing seems to work. I can add a new URL "search/" and then it works, but only with this url.
models.py
class Tag(models.Model):
path = models.CharField(max_length=37,default=0)
name = models.CharField(max_length=35)
description = models.CharField(max_length=200)
image = models.ImageField(default='default.jpg',upload_to='tag_pics')
def __str__(self):
return self.path
views.py
def search(request):
q = request.GET.get('q',None)
items=''
if q is None or q is "":
items = Tag.objects.all()
elif q is not None:
items = Tag.objects.filter(name__contains=q)
paginator = Paginator(items, 3)
page = request.GET.get('page')
items = paginator.get_page(page)
title = "Search"
return render(request, 'blog/search.html',{'items': items, 'title': title})
search.html
{% extends 'blog/base.html' %}
{% block content %}
{% if items %}
<p class="search-count">Found
<strong>
{{ items.paginator.count }}
</strong>
result{{ items.paginator.count|pluralize }}
</p>
{% for i in items %}
{{ i.path }}
{% endfor %}
{% elif request.GET.q %}
<p class="search-no-results">
No results for "<strong>{{ request.GET.q }}"
</p>
{% endif %}
{% endblock %}

Django navbar links disappearing in the post

So sorry probably this is very easy but i learn django and have a problem. My navbar working on index page is perfectly. but when i go contact form or another post url, navbar links disappear.
When i go some post page or my contact form page
1- {{ article.title }} and href links are disappear
Can i ask help ?
my navbar.html
{% load i18n %}
<!-- Menu -->
<div class="menu-wrapper center-relative">
<nav id="header-main-menu">
<div class="mob-menu">Menu</div>
<ul class="main-menu sm sm-clean">
<li>{% trans "HomePage" %}</li>
<li>{% trans "Services" %}</li>
<li>
{% for article in articles %}
{% if article.slug == 'about_us' %}
<a href="{% url 'article:detail' slug=article.slug %}">
{{ article.title }}</a>
{% endif %}
{% endfor %}
</li>
<li>{% trans "HELLO WORLD" %}</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1643 dropdown">
<a title="" href="">{% trans "Producs" %}</a>
<ul role="menu" class=" dropdown-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1644 dropdown">
<a title="Level 2" href="">{% trans "Consult" %}</a>
<ul role="menu" class=" dropdown-menu">
<li >
{% for category in category %}
{% if category.name == 'consult' %}
{% for article in category.get_article %}
<a title="{{ article.title }}" href="{% url 'article:detail' slug=article.slug %}"> <p> {{ article.title }}</p></a>
{% endfor %}
{% endif %}
{% endfor %}</li>
</ul>
</li>
<li>
{% for category in category %}
{% if category.name == 'header' %}
{% for article in category.get_article %}
<a title="{{ article.title }}" href="{% url 'article:detail' slug=article.slug %}"> <p> {{ article.title }}</p></a>
{% endfor %}
{% endif %}
{% endfor %}
</li>
</ul>
</li>
<li>{% trans "İletişim" %}</li>
</ul>
</nav>
</div>
article/views.py
from django.shortcuts import render, get_object_or_404
from .models import Article, Category
from django.core.paginator import Paginator
from django.utils.translation import gettext as _
# Create your views here.
def articles(request):
keyword = request.GET.get("keyword")
if keyword:
articles = Article.objects.filter(title__contains=keyword)
paginator = Paginator(articles, 1)
page = request.GET.get('page')
articles = paginator.get_page(page)
return render(request,"articles.html",{"articles":articles})
articles = Article.objects.all()
paginator = Paginator(articles, 10)
page = request.GET.get('page')
articles = paginator.get_page(page)
return render(request, "articles.html", {"articles":articles})
def index(request):
articles = Article.objects.all()
category = Category.objects.all()
context = {
"articles": articles,
"category": category,
}
return render(request, 'index.html', context)
def detail(request,slug):
# article = Article.objects.filter (id = id).first()
article = get_object_or_404(Article, slug = slug)
category = Category.objects.all()
return render(request, "detail.html", {"article":article, "category":category,})
def category_detail(request,slug):
template = "category_detail.html"
category=get_object_or_404(Category,slug=slug)
article=Article.objects.filter(category=category)
context = {
'category' : category,
'article' : article,
}
return render(request,template,context)
def category_page(request):
object_list = Category.objects.all()
context = {'object_list': object_list,}
return render(request, 'detail.html', context)
contact_form/views.py
from django.views.generic.edit import FormView
from .forms import ContactForm
try:
from django.urls import reverse
except ImportError: # pragma: no cover
from django.core.urlresolvers import reverse # pragma: no cover
class ContactFormView(FormView):
form_class = ContactForm
recipient_list = None
template_name = 'contact_form/contact_form.html'
def form_valid(self, form):
form.save()
return super(ContactFormView, self).form_valid(form)
def get_form_kwargs(self):
if self.recipient_list is not None:
kwargs.update({'recipient_list': self.recipient_list})
return kwargs
def get_success_url(self):
return reverse('contact_form_sent')

My paginator won't show the number of pages

for some reason my paginators not working properly on my post_list page, but it works for my tags_list_page and its almost identical. It wont display the number of pages. Heres my code for them
post list.html pagination
<div class="text-center" style="margin-bottom: 20px">
<ul class="pagination">
{% if object_list.has_previous %}
<li><<</li>
<li><a href="?{{ page_request_var }}={{ object_list.previous_page_number }}
{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">prev</a></li>
{% endif %}
{% for i in paginator.page_range %}
<li {% if page_obj.number == i %} class="active" {% endif %}>{{i}}<li>
{% endfor %}
{% if object_list.has_next %}
<li><a href="?{{ page_request_var }}={{ object_list.next_page_number }}
{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">next</a></li>
<li>>></li>
{% endif %}
</ul>
tags list.html pagination
<div class="text-center" style="margin-bottom: 20px">
<ul class="pagination">
{% if queryset.has_previous %}
<li><<</li>
<li><a href="?{{ page_request_var }}={{ queryset.previous_page_number }}
{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">prev</a></li>
{% endif %}
{% for i in paginator.page_range %}
<li {% if page_obj.number == i %} class="active" {% endif %}>{{i}}<li>
{% endfor %}
{% if queryset.has_next %}
<li><a href="?{{ page_request_var }}={{ queryset.next_page_number }}
{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">next</a></li>
<li>>></li>
{% endif %}
</ul>
my views
def post_list(request):
today = timezone.now().date()
queryset_list = Post.objects.active()
if request.user.is_staff or request.user.is_superuser:
queryset_list = Post.objects.all()
paginator = Paginator(queryset_list, 8)
page_request_var = 'page'
page = request.GET.get(page_request_var)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
template = "posts/post_list.html"
name = "user"
count = queryset_list.count()
context = {
"object_list": queryset,
"name": name,
"page_request_var": page_request_var,
"today": today,
"count": count
}
return render(request, template, context)
def tag_list(request, slug=None):
today = timezone.now().date()
instance = get_object_or_404(Tag, slug=slug)
ins = instance.post_set.all()
queryset_list = Post.objects.active()
if request.user.is_staff or request.user.is_superuser:
queryset_list = ins
paginator = Paginator(queryset_list, 9)
page_request_var = "tags"
page = request.GET.get(page_request_var)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
hey = paginator.num_pages
kount = queryset_list.count()
name = "Tags list"
context = {
"queryset": queryset,
"paginator": paginator,
"page_request_var": page_request_var,
"hey": hey,
"title": "posts",
"name": name,
"today": today,
"kount": kount
}
return render(request, "posts/tag_list.html", context)
It works for the tags pagination fine as I said. dont know whats going on
It was working fine. Any help is appreciated
You're not passing the paginator to the template in the post_list view.

Categories

Resources