Django Pagination Issue - django

I wanna show pagination for my objects that has specific foreign key, with help of documentation, I'm using this:
def baslik_handle(request, title):
baslik, created = Baslik.objects.get_or_create(title=title)
entryler2 = Entry.objects.filter(baslik=baslik).order_by('timestamp')
paginator = Paginator(entryler2, 10)
page = request.GET.get('page')
try:
sayfalar = paginator.page(page)
except PageNotAnInteger:
sayfalar = paginator.page(1)
except EmptyPage:
sayfalar = paginator.page(paginator.num_pages)
ctx = {'entryler2':entryler2, 'sayfalar':sayfalar}
return render(request, "baslik/tek.html", ctx)
for html:
{% for entry in entryler2 %}
{{ entry }}<br>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if sayfalar.has_previous %}
<i class="fa fa-arrow-left"></i>
{% endif %}
<span class="current">
{{ sayfalar.number }} / {{ sayfalar.paginator.num_pages }}
</span>
{% if sayfalar.has_next %}
<i class="fa fa-arrow-right"></i>
{% endif %}
</span>
</div>
after all this pagination is not working. It just calculate the page numbers and don't separate objects to pages.
For instance I have 26 "Entry"s that have same Baslik foreign key. When I look to its pages, it just list all 26 "Entry"s in all 3 pages. What's wrong with my code? What should I do to fix it? Thanks.

Replaced this:
{% for entry in entryler2 %}
to this:
{% for entry in sayfalar %}
and it's fixed.

Related

HTMX not working when using paginate with infinite-scroll

I have a product card in my Django Application, when clicked, adds to cart. I'm using infinite-scroll and django-pagination.
The issue is with the pagination, however. The first page of results works wonderfully with HTMX. However, the second page and all pages beyond does not work on click. Upon inspecting the page, the html does appear to be rendered properly and I can see the hx-get call with the proper url. But upon clicking, nothing happens.
Maybe I'm missing something obvious here, but any help would be appreciated!
HTML
<div class="container"
data-infinite-scroll='{ "path": ".pagination__next", "append": ".product-card", "history":"false"}'>
{% block content %}
{% include 'includes/cards.html' %}
{% include 'includes/sidebar.html' %}
{% endblock content %}
</div>
<ul class="pagination mt-50 mb-70">
{% if products.has_previous %}
<li class="page-item"><a class="page-link" href="?page={{ products.previous_page_number }}"><i class="fa fa-angle-left"></i></a></li>
{% endif %}
<li class="page-item"><a class="page-link" href="#">{{ products.number }}</a></li>
{% if products.has_next %}
<li class="page-item"><a class="pagination__next" href="?page={{ products.next_page_number }}"><i class="fa fa-angle-right"></i></a></li>
{% endif %}
</ul>
views.py
def shop(request):
anabanner = AnaBanner.objects.all()
gender = Gender.objects.all()
categories = Category.objects.all()
colors = Color.objects.all()
materials = Material.objects.all()
query = request.GET.get('query','')
products = Product.objects.all().order_by('-pk')
if query:
products = products.filter(
Q(name__icontains=query)|
Q(sub_name__icontains=query)
).distinct()
paginator = Paginator(products, 8)
page = request.GET.get('page')
products = paginator.get_page(page)
context = {'products':products,'categories':categories,'gender':gender,'anabanner':anabanner,'colors':colors,'materials':materials}
return render(request, 'shop.html', context)
Button
<div class="button">
<div class="button-layer"></div>
<button name="ekle"
href ="#"
hx-get="{% url 'add_to_cart' product.id %}"
hx-target="#menu-cart-button"
hx-swap="outerHTML"
class="btn btn-outline-secondary add-btn update-cart">Sepete Ekle</button>
</div>
Here i my Infinite scroll pattern django with HTMX
urls.py
highlights_urls = [
path('<slug:slug>/',
views.highlight_detail,
name='highlight_detail',
),
]
urlpatterns = [
path('highlights/', include(highlights_urls)),
]
views.py
def highlight_detail(request, slug: str):
object: Highlight = get_object_or_404(Highlight, slug=slug)
template_name = 'highlight/highlight-detail.html'
if request.htmx:
template_name = 'highlight/partials/highlight-detail-partial-elements.html'
page_number = request.GET.get('page', default=1)
paginator = Paginator(object.products.all(), settings.PAGINATION_PAGE_SIZE)
page_obj = paginator.get_page(page_number)
context = {
'object': object,
'page_obj': page_obj
}
return TemplateResponse(request, template=template_name, context=context)
highlight-detail.html
<section class="padding-top">
<div class="container">
<header class="section-heading">
<h3 class="section-title">{{ object.name }}</h3>
</header>
<div class="row" hx-indicator=".htmx-indicator">
{% include './partials/highlight-detail-partial-elements.html' %}
</div>
</div> <!-- container end.// -->
highlight-detail-partial-elements.html
{% for product in page_obj %}
<div
{% if forloop.last and page_obj.has_next %}
hx-get="{% url 'highlight_detail' object.slug %}?page={{ page_obj.number|add:1 }}"
hx-trigger="revealed"
hx-swap="afterend"
hx-target="this"
{% endif %}
class="col-6 col-sm-4 col-md-3 col-lg-3 col-xl-3">
{% include 'highlight/includes/product-card.html' with object=product %}
</div>
{% endfor %}

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>

Django - How to load paginated Page (next page) into my Template?

I have a model named "Person" (List of names).
6 Persons named "Anne". My Pagination is 2 per Page.
When i start a search query on my page for "Anne". I get the Response of "6 Results", it shows me the first two Results and it displays "Page 1 of 3. Next. So far everything fine. but when i press "next" the Browser only updates to
..../post_searchtwo/?page=2 but the next two Results will not show up.
(Using Django version 2.2.2 with PostgreSQL 11)
thanks in advance.
views.py
def post_searchtwo(request):
form = SearchForm()
query = None
results = []
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
query = form.cleaned_data['query']
results = Person.objects.annotate(
search=SearchVector('city', 'last_name', 'first_name')
).filter(search=query)
paginator = Paginator(results, 2) # --- Show 2 items per page
page = request.GET.get('page')
try:
post_list = paginator.page(page)
except PageNotAnInteger:
post_list = paginator.page(1)
except EmptyPage:
post_list = paginator.page(paginator.num_pages)
context = {
'form': form,
'query': query,
'page': page,
'post_list': post_list,
'results': results
}
return render(request,'search/post_searchtwo.html', context)
my template / post_searchtwo.htnl
{% extends 'base.html' %}
{% load static %}
{% block custom_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/home_styles.css' %}">
{% endblock %}
{% block content %}
<form action="." method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% if query %}
<h3>Posts containing "{{ query }}"</h3>
<h3>
{% with results.count as total_results %}
Found {{ total_results }} result{{ total_results|pluralize }}
{% endwith %}
</h3>
{% for post in post_list %}
<h4>
{{ post.first_name }} {{ post.last_name }}
</h4>
{% empty %}
<p>Theren are no results for your query.</p>
{% endfor %}
<div class="col-6 offset-md-3">
{% include "pagination.html" with page=post_list %}
</div>
{% endif %}
{% endblock %}
.../pagination.htnl
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
Next
{% endif %}
</span>
</div>
Update: Thanks to #Daniel Roseman
as Daniel pointed out (down below) here the changes.
.../pagination.htnl
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
Next
{% endif %}
</span>
</div>

How to store form data in form pagination using session?

I'm working on a quiz. The quiz has multiple questions - forms. Since there may be many questions, I've created a pagination for these forms. Everything seems to work correctly but only the data from forms on last page are sent to server.
How to hold the data from previous pages so I can send all forms then to server?
I'm considering using session but can't figure out how to make it work. As you can see, all questions are in one form with method post. But pagination are GET methods.
def take_quiz(request,id):
if request.method == 'POST':
quiz = get_object_or_404(models.LanguageQuiz, pk=id)
sitting = get_object_or_404(models.Sitting, quiz=quiz, user=request.user)
for k,v in request.POST.iteritems():
if 'choice-for' in k:
q = Question.objects.get(pk=k.split('-')[-1])
choice = Choice.objects.get(pk=v)
sitting_question = get_object_or_404(SittingQuestion,sitting=sitting,question=q)
sitting_question.answer = choice
sitting_question.save()
correct_answers = len([x for x in sitting.sitting_questions.all() if x.answer.correct])
result = float(correct_answers)/sitting.sitting_questions.all().count() * 100
return render(request,'quiz/result.html',context={'result':result,
'level':level,
'quiz':quiz})
if request.method == 'GET':
with transaction.atomic():
quiz = get_object_or_404(models.LanguageQuiz, pk=id)
if models.Sitting.objects.filter(quiz=quiz, user=request.user).exists():
sitting = get_object_or_404(models.Sitting, quiz=quiz, user=request.user)
check_expired_sitting(sitting)
sitting.delete()
sitting = models.Sitting.objects.create(quiz=quiz, user=request.user)
sitting.load_questions()
questions = [x.question for x in sitting.sitting_questions.all()]
paginator = Paginator(questions,2)
page_num = request.GET.get('page',1)
page = paginator.page(page_num)
context = {'page':page,
'quiz':quiz}
return render(request,'quiz/quiz.html',context=context)
TEMPLATE
{% extends 'base.html' %}
{% block content %}
<h1>{{ quiz.name }}</h1>
<br><br><br>
<form action="" method="post">{% csrf_token %}
{% for question in page.object_list %}
<div class="question">
<h3>{{ question.text }}</h3>
<div class="choices">
{% for choice in question.get_choices_list %}
<input type="radio" name="choice-for-question-{{ question.id }}"
id="choice-{{ question.id }}-{{ forloop.counter }}" value="{{ choice.id }}"/>
<label for="choice-{{ question.id }}-{{ forloop.counter }}">{{ choice.text }}</label><br/>
{% endfor %}
</div>
</div>
{% endfor %}
{% if not page.has_next %}
<button class='accordion' type="submit">Submit Quiz</button>
{% endif %}
</form>
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
next
{% endif %}
</span>
</div>
{% endblock %}

Django pagination showing pages but still all objects

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.