Django pagination showing pages but still all objects - django

So I'm attempting to implement the pagination for a website that i'm working on, but it seems not to work completely.
class ExampleListView(FormMixin, ListView):
model = Example
template_name = "example.html"
paginate_by = 3
context_object_name = "example_list"
allow_empty = True
page_kwarg = 'page'
paginate_orphans = 0
form_class = ExampleForm
Then in the html I have the following
<tbody>
{% for formset_form in formset %}
...
{% endfor %}
...
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
Previous
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
Next
{% endif %}
</span>
</div>
{% else %}
<p></p>
{% endif %}
I currently have 5 forms there in the table, and paginated it by 3. What it does is that is displays Page 1 of 2 Next, like it should, but it displays all of the forms on the pages.

The Django ListView is meant to render 'A page representing a list of objects.'. You try to display a paginated list of formsets. Interesting thought, but not what ListView does.
This answer to a previous question may help you to achieve what you want.

Related

Django - pagination based on search criteria

I am having issues getting results when clicking on page 2 and above - most likely due to url issues. I have a list of names and if I search on e.g. "John" I want them to be separated by pages if number of names > e.g. 10.
My Views are as follows: (searching works fine)
def name_search(request):
if 'q' in request.GET:
q=request.GET.get('q', '')
pvt_list = pvt_data.objects.filter(full_name__icontains=q)
#Pagination
p = Paginator(pvt_list, 10) # Show 10 contacts per page.
page_num = request.GET.get('page', 1)
try:
page = p.page(page_num)
except PageNotAnInteger:
page = p.page(1)
except EmptyPage:
page = p.page(1)
context = {'items' : page}
return render(request, 'home/name_search.html', context)
else:
return render(request, 'home/name_search.html')
My urls.py file is
urlpatterns = [
...
path('name_search', views.name_search, name='name_search'),
...
]
My html file is
{% for pvt in items %}
{{ pvt.full_name }}
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if items.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ items.number }} of {{ items.paginator.num_pages }}.
</span>
{% if items.has_next %}
next
{% endif %}
</span>
</div>
When I search, I get the following link 'http://127.0.0.1:8000/name_search?q=John' with the first 10 names correct.
When I click on next button I get the following link:
http://127.0.0.1:8000/name_search?page=2
Changing the link manually to
http://127.0.0.1:8000/name_search?q=John/page=2
does not work...
Any response is appreciated :-)
a solution might be to add your search parameter to your href.
so instead of:
next
try:
next
You are almost there, you need to pass the query to the next/previous pages as well.
{% for pvt in items %}
{{ pvt.full_name }}
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if items.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ items.number }} of {{ items.paginator.num_pages }}.
</span>
{% if items.has_next %}
next
{% endif %}
</span>
</div>

Is there a way in Django to load a template in 'sections' or 'chunks' a sort of pagination as you scoll?

The reason I ask is that I'm parsing a large List into a Django template, we're talking about 100,000 items being rendered into a table and it's painfully slow at loading!
or is there a method that I've completely missed?
I'm currently using {% regroup %} to group headers together.
with the Paginator class
from django.views.generic import ListView
from myapp.models import Contact
class ContactList(ListView):
paginate_by = 2
model = Contact
and the template
{% 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>
https://docs.djangoproject.com/en/3.1/topics/pagination/

Django BooleanField if statement doesnt return content

For some reason when checking to see if BooleanField post.featured is true I get no output. If I remove that it works fine but not as I intend.
<div class="carousel-inner">
{% for post in object_list%}
{% if post.featured is True %}<!-- This post.featured is BooleanField -->
{% if forloop.first %}
<div class="carousel-item active">
{% else %}
<div class="carousel-item">
{% endif %}
<div class="col-md-6 px-0">
<h1 class="display-4 font-italic">{{ post.title }}</h1>
<p class="lead my-3">{{ post.hook }}</p>
<p class="lead mb-0">
<a href="{% url 'article-details' post.pk %}" class="text-white fw-bold">
Continue reading...
</a>
</p>
</div>
</div>
{% endif %}<!-- and this -->
{% endfor %}
</div>
Heres how it looks like when not checking if post.featured == true:
However, content doesnt render with {% if post.featured is True %} or {% if post.featured %}
Can someone please explain what im doing wrong
EDIT:
Submiting my view:
class Home(ListView):
model = Post
template_name = 'home.html'
You should not filter in the template. This is not only inefficient, but a template is not meant to implement business logic, only rendering logic: a template should not be concerned with what it renders, it should only be concerned with rendering the data in a pleasant way.
You should filter in the ListView:
class Home(ListView):
model = Post
template_name = 'home.html'
queryset = Post.objects.filter(featured=True)
This will filter at the database side.
If you need both the featured items, and the ones that are not featured, you can make two queries:
class Home(ListView):
model = Post
template_name = 'home.html'
queryset = Post.objects.filter(featured=True)
def non_featured(self):
return Post.objects.filter(featured=False)
then you can render the non-featured items with:
{% for post in view.non_featured %}
…
{% endfor %}

Django inclusion_tag contents not displaying

I cannot get the contents of an inclusion_tag to display. I am not getting an errors so i know that the tag is registering and I am almost certain that it is loading correctly. The tag is created in crudapp/templatetags/crudapp_tags.py
from django import template
register = template.Library()
#register.inclusion_tag("forum.html")
def results(poll):
form = 'blah'
return {'form': form}
templates/forum.html
{% extends 'index.html' %}
{% load crudapp_tags %}
{% results poll %}
<p>aaa</p>
{% block homepage %}
<p>bbb</p> <!-- Only this displays -->
{% if form %}
<p>Form exists</p>
{% endif %}
{% for item in form %}
<p>This is {{ item }}</p>
{% endfor %}
<div>
<p>{% if user.is_authenticated %}Add a New Topic: <span class="glyphicon glyphicon-plus"></span>{% endif %}</p>
</div>
<div>
<p>{{ totalposts.count }} posts, {{ totaltopics.count }} topics, {{ totalusers.count }} users, {{ totalviews.numviews}} views</p>
</div>
{% endblock %}
The file set up is as follows,
If you are using an inclusion tag, then the tag renders another template. You need to move the code that uses form out of forum.html and into a new template, e.g. results.html
results.html
{% if form %}
<p>Form exists</p>
{% endif %}
{% for item in form %}
<p>This is {{ item }}</p>
{% endfor %}
Then change your tag to use this template
#register.inclusion_tag("results.html")
def results(poll):
form = 'blah'
return {'form': form}
Finally, since you are extending a template, you need to move then tag into a block, otherwise the result won't be used.
{% block homepage %}
{% results poll %}
...
{% endblock %}
If you want to add an item to the template context instead of rendering another template, then you want a simple tag instead.
#register.simple_tag
def fetch_result():
result = ['foo', 'bar']
return result
Then in your template:
{% fetch_result as result %}
{% for item in result %}
<p>This is {{ item }}</p>
{% endfor %}
The {% fetch_result as result %} works for simple tags in Django 1.9+. In earlier versions, you want an assignment tag.

Object not iterable with django's pagination

I have a template showing a list of events. To prepare list of events I'm using generic views, and set 'paginate_by' parameter. Strangely when I load my page I see :
TemplateSyntaxError at /event/latest/
Caught an exception while rendering: 'int' object is not iterable
in 9th line of pagination.html template :
{% if is_paginated %}
{% load i18n %}
<div class="pagination">
{% if page_obj.has_previous %}
<< Prev
{% else %}
<span class="disabled prev"><< Prev</span>
{% endif %}
#here {% for page in pages %}
{% if page %}
{% ifequal page page_obj.number %}
<span class="current page">{{ page }}</span>
{% else %}
{{ page }}
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
Next >>
{% else %}
<span class="disabled next">Next >></span>
{% endif %}
</div>
{% endif %}
Here is my view :
def events_nearest(request):
events = Event.nearest.all()
return object_list(request,
queryset = events,
extra_context = {'title': 'Nearest events'},
paginate_by = 12,
template_name = 'event/events_date.html')
And model :
class NearestManager(models.Manager):
def get_query_set(self):
return super(NearestManager, self).get_query_set().order_by('-data')
class Event(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=255, unique=True, verbose_name='Slug')
about = models.TextField()
city = models.ForeignKey(City)
objects = models.Manager()
nearest = NearestManager()
Any ideas what can cause this ?
pages variable is the number of pages, which is int and hence the error: 'int' object is not iterable
you should be looping over page_range
{% for page in page_range %}
I met the same error. There is a note at
https://docs.djangoproject.com/en/dev/topics/pagination/
Changed in Django Development version: Previously, you would need to use {% for contact in contacts.object_list %}, since the Page object was not iterable.
So {% for page in pages.object_list %} could probably solve your problem.
For anybody stumbled upon this post:
As with Django 1.4 and later (as far as I know), the iterable object for pagination is now paginator.page_range , i.e. the for loop should be
{% for page_num in paginator.page_range %}
In your error line #9 {% for page in pages %} what exactly is pages
Can't see it in your code anywhere.