问题
I've been using django built-in pagination (is_paginated) in few of my pages. They are all working fine. Except for the search page where the pagination should only appear based on the filtered queryset.
I've checked through few other thread but it ain't helping much.
How do I use pagination with Django class based generic ListViews?
Django template tag exception
Here's a mini version of what I have so far:-
1)views.py
class SearchBookView(ListView):
template_name = 'books/search_book.html'
paginate_by = '2'
context_object_name = 'book'
form_class = SearchBookForm
def get(self, request):
form = self.form_class(request.GET or None)
if form.is_valid():
filtered_books = self.get_queryset(form)
context = {
'form' : form,
'book' : filtered_books,
}
else:
context = {'form': form}
return render(request, self.template_name, context)
def get_queryset(self, form):
filtered_books = Book.objects.all()
if form.cleaned_data['title'] != "":
filtered_books = filtered_books.filter(
title__icontains=form.cleaned_data['title'])
return filtered_books
def get_context_data(self):
context = super(SearchBookView, self).get_context_data()
return context
2) search_book.html (template)
{% crispy form %}
{% if book %}
<p>Found {{ book|length }} book{{ book|pluralize }}.</p>
{% for book in book %}
<div class="card">
<div style="height:170px; border:solid #111111;" class="col-md-3">
Ima
</div>
<div class="whole-card col-md-9">
<div class="title">"{{ book.title }}"</div>
<div>{{ book.description }}</div>
<a href="{% url 'book:detail' book.id %}" class="btn">Read More</a>
</div>
</div>
{% endfor %}
{% else %}
<p>No book matched your searching criteria.</p>
{% endif %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
forms.py
class SearchBookForm(forms.Form):
title = forms.CharField(max_length=20)
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.add_input(Submit('search', 'Search', css_class='btn'))
self.helper.form_method = 'GET'
self.helper.layout = Layout('title')
super(SearchBookForm, self).__init__(*args, **kwargs)
------------------UPDATE------------------
Though I understand Daniel Roseman's answer but as I am fairly new to django, I am not sure how to implement the whole thing, hitting plenty of "X not accessible, X is not attribute of Y" and etc. After much digging, I found some other useful posts on this same matter.
Django: Search form in Class Based ListView
Updating context data in FormView form_valid method?
Django CBV: Easy access to url parameters in get_context_data()?
Django class based view ListView with form
URL-parameters and logic in Django class-based views (TemplateView)
Another problem I encounter is I am unable to access the parameters in URL using self.kwargs as what suggested in most of the posts. In the final link I posted above, Ngenator mentioned that URL parameters has to be accessed using request.GET.get('parameter'). I used that and it's working fine for me.
By combining everything, here's the revised piece of coding I have. Just in case anyone is having the same problem as me.
1) views.py
class SearchBookView(ListView):
template_name = 'books/search_book.html'
paginate_by = '3'
context_object_name = 'book_found'
form_class = SearchBookForm
model = Book
def get_queryset(self):
object_list = self.model.objects.all()
title = self.request.GET.get('title', None)
if title is not None and title != "":
object_list = object_list.filter(title__icontains=title)
else:
object_list = []
return object_list
def get_context_data(self):
context = super(SearchBookView, self).get_context_data()
form = self.form_class(self.request.GET or None)
context.update({
'form': form,
})
return context
2) search_book.html (template)
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load staticfiles %}
{% load bootstrap_pagination %}
{% block title %}Search Page{% endblock %}
{% block content %}
<div class="container">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
{% crispy form %}
{% if book_found %}
<p>Found {{ paginator.count }} book{{ book_found_no|pluralize }}.</p>
{% for book in book_found %}
<div class="wholecard">
<div style="height:170px; border:solid #111111;" class="col-md-3">
Image
</div>
<div class="card col-md-9">
<div class="card-title">"{{ book.title }}"</div>
<div>{{ book.description }}</div>
<a href="{% url 'books:detail' book.id %}" class="btn">Read More</a>
</div>
</div>
{% endfor %}
{% else %}
<p>No book matched your searching criteria.</p>
{% endif %}
{% bootstrap_paginate page_obj %}
</div>
{% endblock %}
And I ended up using jmcclell's bootstrap-pagination also for pagination. Saved me lots of time! Good stuff...
回答1:
You've specifically overridden the get
method so that it defines its own context, and never calls the default methods, so naturally none of the default context bars are available.
Don't do that; you should almost never be overriding the get and post methods. You should probably move all the form stuff directly into get_queryset
.
回答2:
It's working
views.py
class UserListView(ListView):
model = User
template_name = 'user_list.html'
context_object_name = 'users'
paginate_by = 10
def get_queryset(self):
return User.objects.all()
templates/user_list.html
{% if is_paginated %}
<nav aria-label="Page navigation conatiner">
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li><a href="?page={{ page_obj.previous_page_number }}" class="page-link">« PREV </a></li>
{% else %}
<li class="disabled page-item"><a class="page-link">PREV !</a></li>
{% endif %}
{% for i in %}
{{ i }}
{% endfor %}
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}" class="page-link"> NEXT »</a></li>
{% else %}
<li class="disabled page-item"><a class="page-link">NEXT !</a></li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
来源:https://stackoverflow.com/questions/33431092/is-paginated-not-working-for-django-generic-views