Django - pagination based on search criteria - django

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>

Related

Get Direct URL for uploads in search - Wagtail

I have customized my search to look at images and documents as part of that search. This is working fine. However I am not sure how to get the URL to the uploaded images/documents that are returned. Ideally there would be a link to download/display in browser. I am ok with the ../media/images/xxx url. But I can't seem to figure out how to get that data in the template. Thoughts? Search is performed by this.
# Search
if search_query:
results = []
page_results = Page.objects.live().search(search_query)
if page_results:
results.append({'page': page_results})
doc_results = Document.objects.all().search(search_query)
if doc_results:
results.append({'docs': doc_results})
img_results = Image.objects.all().search(search_query)
if img_results:
results.append({'image': img_results})
search_results = list(chain(page_results, doc_results, img_results))
query = Query.get(search_query)
# Record hit
query.add_hit()
else:
search_results = Page.objects.none()
And the html looks like this
{% if search_results %}
{{ count }} results found.
{% for result in search_results %}
{% for k, v in result.items %}
{% if k == 'page' %}
{% for item in v %}
<p>
<h4>{{ item }}</h4>
Type: Article<br>
Author: {{ item.specific.owner.get_full_name }}<br>
Publish Date: {{ item.specific.last_published_at}}
</p>
{% endfor %}
{% elif k == 'docs' %}
{% for item in v %}
<p>
<h4>{{ item.title }}</h4>
Type: Document<br>
Publish Date: {{ item.created_at }}
</p>
{% endfor %}
{% elif k == 'image' %}
{% for item in v %}
<p>
<h4>{{ item.title }}</h4>
Type: Image<br>
Publish Date: {{ item.created_at }}
</p>
{% endfor %}
{% endif%}
{% endfor %}
{% endfor %}
{% if search_results.has_previous %}
Previous
{% endif %}
{% if search_results.has_next %}
Next
{% endif %}
{% elif search_query %}
No results found
{% endif %}
Django provides the url property to files and images, and wagtail has this also.
{{ item.url }}
Wagtail has a great support for the redirect to files and integrates django-sendfile as well. Both of these methods allow for image downloading.
https://docs.wagtail.io/en/stable/advanced_topics/images/image_serve_view.html
from wagtail.images.views.serve import ServeView
urlpatterns = [
...
re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(action='redirect'), name='wagtailimages_serve'),
]
** Edit below
Generating the image “as foo” to access individual properties - access the underlying image instance
{% image item original as item_img %}
{{ item_img.url }}

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>

In django, pagination is not working for second page and thereafter ,the objects are not displayed

when i click on "next" the objects that should be displayed on the next page is not being displayed.
but the objects are being displayed for the first page.(ie, the correct number of objects as well)
Also what is 'page' in 5th line in views.py?
views.py
def search(request):
context ={}
search_list = Search.objects.all()
paginator = Paginator(search_list, 4) # Show 4 contacts per page
page = request.GET.get('page', 1)
search = paginator.get_page(page)
context['search'] = search
return render(request, "main.html", context)
main.html (template)
{% for result in search %}
<br>
{{ forloop.counter }}
<br>
{{ result.Query }}
<!-- {{ search.Result.name }} -->
<br>
{{ result.json }}
<br>
<br>
{{ result.json.name }}
<br>
<br>
{{ result.json.price }}
<br>
<br>
{{ result.json.author }}
<br>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if search.has_previous %}
« first
previous
{% endif %}
<span class="current">
{{ posts.paginator.count }}
Page {{ search.number }} of {{ search.paginator.num_pages }}.
</span>
{% if search.has_next %}
next
last »
{% endif %}
</span>
</div>
Instead of: page = request.GET.get('page', 1) you need to do just page = request.GET.get('page')
The get_page() method on the next line takes care of displaying first page if request.GET['page'] doesn't exists or contains non-integer value.
Look at your template:
next // missing closing bracket
next

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.

Django Pagination Issue

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.