I have a filter with a dependent drop down for cars makes and models. Since I don't want to display all of them on one page I added a paginator. The issue is the filter works correctly but it does not carry over in the pages
when the filter is active the url looks like
/cars/?manufacture=2&model=2
If i go to the next page all I get is /cars/?page=2
I want something like /cars/?manufacture=2&model=2?page=2
If I print {{ posts|length }}
it does return the proper number of items that are being filtered so there is not issue there
I believe the issue is with the next and previous buttons in the template as they don't pass any parameters in them other then next page. How do i carry the filter into the paginator.
view
def allCarsView(request):
model = Post
myFilter = carFilter(request.GET, queryset=Post.objects.all())
posts = myFilter.qs
page = request.GET.get('page', 1)
paginator = Paginator(posts.order_by('date_posted'), 2)
page_obj = paginator.get_page(page)
page_range = paginator.get_elided_page_range(number=page)
context = {
'posts':posts, 'myFilter':myFilter, 'page_range': page_range,
'page': page, 'paginator': paginator, 'page_obj': page_obj
}
return render(request, 'blog/cars.html', context)
Paginator html
<nav aria-label="Page navigation example " class="paginator">
<nav aria-label="Page navigation example " class="paginator">
<ul class="pagination justify-content-center">
<li class="page-item">
{% if page_obj.has_previous %}
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
{% else %}
</li>
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %} {% for i in page_obj.paginator.page_range %} {% if page_obj.number == i %}
<li class="page-item active" aria-current="page">
<a class="page-link" href="#">{{ i }}</a>
</li>
{% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %} {% endfor %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Previous">
<span aria-hidden="true">»</span>
</a>
{% else %}
</li>
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
Update: From doing more research it does seem that my issue is with the urls in the paginator as they do not carry any parameters. There does not seem to be a best way to do this and the solutions I have tried have yielded nothing.
Update: Attempting to use this post as the solution
view (added under previous code) from django import template register = template.Library()
@register.simple_tag
def url_replace(request, field, value):
dict_ = request.GET.copy()
dict_[field] = value
return dict_.urlencode()
template:
<a class="page-link" href="?{% url_replace request 'page' page_obj.next_page_number %}" aria-label="Previous">
I then get the error
Invalid block tag on line 88: 'url_replace', expected 'elif', 'else' or 'endif'. Did you forget to register or load this tag?
so at the top if I add
{% load url_replace %}
throws the error
'url_replace' is not a registered tag library
Attempt at being able to select page number from paginator
{% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
{% if page_obj.number > i %}
<li class="page-item"><a class="page-link" href="?{% querystring_replace request 'page' page_obj.previous_page_number %}">{{ i }}</a></li>
{% endif %}
{% if page_obj.number < i %}
<li class="page-item"><a class="page-link" href="?{% querystring_replace request 'page' page_obj.next_page_number %}">{{ i }}</a></li>
{% endif %}
{% endif %} {% endfor %}
This can be done using custom template tags as shown in this answer. However, that answer skips over the whole process of creating custom tags, so let me show you how to do that.
Django requires that your custom tags be kept in a folder called templatetags
inside an app. So this is what your app's folder structure must look like:
my-app/
├─ __ini__.py
├─ models.py
├─ views.py
├─ templatetags/
│ ├─ __init__.py
│ ├─ myapp_tags.py
Tip: You can also create a new app specifically for keeping custom tags. That way it becomes easy to re-use them in different projects. Make sure your new app is in INSTALLED_APPS
list.
Now open the myapp_tags.py
file and create the custom tag there:
# myapp_tags.py
from django import template
register = template.Library()
@register.simple_tag
def querystring_replace(request, key, value):
"""Replace the given `key` with the given `value`
in the request's querystring. The rest of the
querystring remains unchanged.
"""
query_dict = request.GET.copy()
query_dict[key] = value
return query_dict.urlencode()
To use this tag in the templates, you'll need to load the file containing the tags:
<!-- load the file containing the tags -->
{% load myapp_tags %}
<!-- now you can use all the tags from myapp_tags -->
{% querystring_replace request 'page' page_obj.next_page_number %}