I have the following template based pagination:
{% for ipage in transactions.paginator.page_range %}
<li {% if ipage == page %} class="active"{%endif%}>{{ipage}} - {{page}}</li>
{% endfor %}
The view page looks like this:
trans_list = Transaction.objects.all()
paginator = Paginator(trans_list, 15)
page = request.GET.get('page')
try:
transactions = paginator.page(page)
except PageNotAnInteger:
transactions = paginator.page(1)
except EmptyPage:
transactions = paginator.page(paginator.num_pages)
context = {
'page':page,
'transactions':transactions,
}
ipage and page both print the page number, but the if doesn't display the active class when they match in the for loop.
How can I get the if to match when the page number and the for loop index match?
That should do the trick.
{% for ipage in transactions.paginator.page_range %}
{% ifequal ipage transactions.number %}
<!-- Do something special for this page -->
{% else %}
<!-- All the other pages -->
{% endifequal %}
{% endfor %}
Related
I am a newbie in Elasticsearch, I just try to create a search engine using it in Django. Overall, the engine shows good results. Unfortunately, it loads a large number of the results. Then, I try to paginate it by regular pagination in Django, after that, the page load error object of type 'Search' has no len().
These are my codes:
view.py
from django.shortcuts import render, redirect
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
from django.core.paginator import Paginator
def search_es(request):
return render(request,'search/search.html')
def results(request):
s = Search(using=Elasticsearch())
keyword = request.GET.get('q') # keyword that want to be found
print(keyword)
if keyword:
# posts = s.query('match_phrase_prefix',head_title=keyword)
# if posts.count() == 0:
posts = s.query(
"multi_match",
query=keyword,
fields=['head_title^5', 'description^5', 'description.ngram'],
# type="phrase_prefix",
)
posts = posts[0: 100]
else:
posts = ''
page = request.GET.get('page', 1)
paginator = Paginator(posts, 10)
try:
users = paginator.page(page)
except PageNotAnInteger:
users = paginator.page(1)
except EmptyPage:
users = paginator.page(paginator.num_pages)
context = {
'page_title': keyword,
'posts': users,
'count': posts.count(),
'keyword': keyword,
}
return render(request,'search/results.html',context)
results.html
{% if posts.has_other_pages %}
<ul class="pagination">
{% if posts.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in posts.paginator.page_range %}
{% if posts.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if posts.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
Hope for every possible solution.
Thank you very much.
ElasticSearch provided two parameters you can use for pagination: from and size. You can refer to https://elasticsearch-dsl.readthedocs.io/en/latest/search_dsl.html#pagination
for example:
posts = s[0:20].query(
"multi_match",
query=keyword,
fields=['head_title^5', 'description^5', 'description.ngram'],
# type="phrase_prefix",
)
to get first page, and page size is 20.
As a continuation of this question Django pagination with bootstrap any my works under my Contacts app I have to ask for your help once more. I have a problem I cannot resolve. I used few suggestions about pagination but all that is changing is the bottom pagination menu. My app is still loading all 5k objects every time, over and over. I am new at this, this app is my first project and this is the final 'big' missing part. I promiss to post final cone when I'm done :)
Best regards.
views.py
def index(request):
contacts_list = contacts.objects.all()
contacts_filter = LFilter(request.GET, queryset=contacts_list)
paginator = Paginator(contacts_list, 50)
try:
page = int(request.GET.get('page','1'))
except:
page = 1
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
index = contacts.number - 1
max_index = len(paginator.page_range)
start_index = index - 3 if index >= 3 else 0
end_index = index + 3 if index <= max_index - 3 else max_index
page_range = paginator.page_range[start_index:end_index]
return render(
request, 'index.html',
context={'filter': contacts_filter,
'contacts': contacts,
'page_range': page_range, }
)`
index.py
{% for obj in filter.qs %}
Code for contact information to display
{% endfor %}
<div class="prev_next">
{% if contacts.has_previous %}
<a class="prev btn btn-info" href="?page={{contacts.previous_page_number}}">Prev</a>
{% endif %}
{% if contacts.has_next %}
<a class="next btn btn-info" href="?page={{contacts.next_page_number}}">Next</a>
{% endif %}
<div class="pages">
<ul>
{% for pg in page_range %}
{% if contacts.number == pg %}
<li>{{pg}}</li>
{% else %}
<li>{{pg}}</li>
{% endif %}
{% endfor %}
</ul>
</div>
<span class="clear_both"></span>
</div>
I follow this Document of djangoproject.com : https://docs.djangoproject.com/en/1.8/topics/pagination/. But it is too simple. It is only Next and Previous button.
Now I want create pagination with more features such as http://i.imgur.com/ZiFeAqG.jpg.
This is code:
View.py
def hire(request):
hire_article_list = hire_article.objects.all().order_by('-id')
#hire_article_list = hire_article.objects.order_by("-publication_date")
paginator = Paginator(hire_article_list, 2) # Show 25 contacts per page
page = request.GET.get('page')
try:
hire_article_s = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
hire_article_s = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
hire_article_s = paginator.page(paginator.num_pages)
#return render_to_response('hire/list.html', {"page_list": page_list})
context = {'hire_article_s': hire_article_s}
return render(request, 'hire/list.html', context)
list.html
{% for j in hire_article_s %}
{# Each "j" is a page_list model object. #}
<li>{{ j.hiring}}</li>
{% endfor %}
{% if hire_article_s.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ hire_article_s.number }} of {{ hire_article_s.paginator.num_pages }}.
</span>
{% if hire_article_s.has_next %}
next
{% endif %}
</span>
</div>
I had a similar need last week and found this super useful gist (https://gist.github.com/jsatt/8183993) that worked fine (though I'm not sure why it wouldn't work till I put request in the function parameters). It's a subclass of django's Paginator function. You could put this in a utility file and call it whenever you want to use Paginate with the range.
For instance, I had mine in a file called utils.py, which is in my core app.
views.py
from core.utils import paginate
def hire(request):
hire_article_list = hire_article.objects.all().order_by('-id')
'''
Show 25 contacts per page, with a page range of 5, which means if you are
on page 8, it shows links to pages 6,7,8,9,10.
'''
hire_article_s = paginate(request, hire_article_list, 25, 5)
context = {'hire_article_s': hire_article_s}
return render(request, 'hire/list.html', context)
list.html
{% if hire_article_s.has_previous %}
previous
{% endif %}
{% for range in hire_article_s.neighbor_range %}
{% if range == hire_article_s.number %}
<li class="pagination__item active ">{{ range }}</li>
{% else %}
<li class="{% if range == hire_article_s.number %}active {% endif %}">{{ range }}</li>
{% endif %}
{% endfor %}
{% if hire_article_s.has_next %}
next
{% endif %}
Hope this helps.
UPDATE
The above code has been edited a bit. I've added the context and the template format. Note that I'm using a loop to go through {{ hire_article_s.neighbor_range }} and print out the page numbers. I also do a check to highlight the current page's number. the This should work, as it's pretty much my own code with your own variable names.
So I am trying to use pagination to display all the matching classes available on a certain day, but following the pagination docs, each page just returns the same 10 results. What am I missing/ what should I have in urlconf? Additionally, if I try using pagination to display search results, I get the error "The view search.views.search_classes didn't return an HttpResponse object" when I try to select the next page. Any input into either or both examples would be greatly appreciated.
#views.py
def upcoming_class_list(request, day):
try:
day = int(day)
except ValueError:
raise Http404()
today = datetime.date.today()
day_x = datetime.date.today() + datetime.timedelta(days=day)
day_x_classes = UpcomingClasses.objects.filter(class_date=day_x)
all_matches = day_x_classes
paginator = Paginator(all_matches, 10)
page = request.GET.get('page')
try:
matches = paginator.page(page)
except PageNotAnInteger:
matches = paginator.page(1)
except EmptyPage:
matches = paginator.page(paginator.num_pages)
return render_to_response('preview.html', {'today': today, 'tomorrow': tomorrow,
'past_classes': past_classes, 'day_x': day_x, 'day': day,
'day_x_classes': day_x_classes, 'yesterday': yesterday, 'matches': matches,
'page': page}, context_instance = RequestContext(request))
#urls.py
(r'^upcoming_class_list/plus/(\d{1,2})/$', upcoming_class_list),
#preview.html
<h3>Classes for {{ day_x }}</h3>
{% if matches %}
<div class="pagination">
<span class="step-links">
{% if matches.has_previous %}
« previous
{% endif %}
<span class="current">
Page {{ matches.number }} of {{ matches.paginator.num_pages }}
</span>
{% if matches.has_next %}
next »
{% endif %}
</span>
</div>
{% if day_x_classes %}
<ul type=none>
{% for class in day_x_classes %}
<li>
<ul type=none>
<li><strong>{{ class.type }}</strong></li>
<li>Teacher: {{ class.teacher }}</li>
<li>Class Description: {{ class.description }}</li>
...
</ul>
</li><br />
{% endfor %}
</ul>
{% endif %}
{% else %}
<p>There are currently no scheduled upcoming classes for {{ day_x }}.</p>
{% endif %}
Anything coming from GET or POST will be a string, so you're always hitting that first exception. Try:
try:
matches = paginator.page(int(page))
except (PageNotAnInteger, ValueError):
matches = paginator.page(1)
It's hard to guess at the rest of the issue without seeing the rest of your view. Looking at other bits in the view, you shouldn't need the check for day being an int as you've already assured that in your urls.py file with the regex, but you don't call the Http404 object, it's simply raise Http404
Ok so I figured out the answer to both of my questions. The first part was because I was making a dumb mistake in my template. The view urlconf were correct, but in my template, my for loop stated:
{% for class in day_x_classes %}
when I should have been using
{% for class in matches %}
since matches was being paginated, not day_x_classes.
As far as paginating my search results, I simply needed to edit the "previous" and "next" buttons from
« previous
from
« previous
to account for q (the searched term).
I hope that my mistakes will be able to help someone who was stuck in a similar situation.
I am trying to return paginated objects and then iterate through them. Seems pretty straightforward. Apparently I'm missing something, though. Can you spot the error?
The view:
def thumbnails(request):
page = request.GET.get('page', 1)
album = request.GET.get('a', None )
if (album):
objects = Album_Photos.objects.filter(id=album)
else:
objects = None
if (objects):
paginator = Paginator(objects, 25)
try:
photos = paginator.page(page)
except PageNotAnInteger:
photos = paginator.page(1)
except EmptyPage:
photos = None #paginator.page(paginator.num_pages)
return render_to_response('photos/thumbnails.html', {'photos': photos}, context_instance = RequestContext(request))
The template:
{% if photos %}
{% for photo in photos %}
<img src="{{photo.original.url}}">
{% endfor %}
{%endif%}
The error:
TemplateSyntaxError at /photos/thumbnails/
Caught TypeError while rendering: 'Page' object is not iterable
1 {% if photos %}
2 {% for photo in photos %}
3 <img src="{{photo.original.url}}">
4 {% endfor %}
5 {%endif%}
Well, unlike the example in the Django docs (at least in my case), you must append .object_list to that Page object.
{% if photos %}
{% for photo in photos.object_list %}
<img src="{{photo.original.url}}">
{% endfor %}
{%endif%}
This has been changed in django: somewhere between version 1.3 and 1.6, Paginator.Page has been made iterable.
If you follow the example from the current documentation, while using an older version of django, you get this error.
Either append .object_list as Brian D. said, or upgrade django.