Django List View With Show More
This post is part of the Django Tricks series
- Django Rest Framework: Multiple post
- Make a Excel Django combo
- Django With Barcode and Qrcode
- Django Return Pdf With Reportlab
- Django List View With Show More
- Message and Allert With Django and Boostrap
- Csv From Django
- Django Generate Barcode With Reportlab
- Add Minor Things to Django for templating
- Htmx Django and Django Table2
Sometime you want to have infinite scrolling in a Django ListView. And there are good post about this topic on the internet like this one but nothing about infinite scrolling with filters.
Basic setup
In this tutorial I assume you have a Product django model and a class view like this:
model.py
from django.db import model
class Product(models.Model):
title = models.CharField(max_length=250)
description = models.TextField()
def __str__(self):
return self.titleviews.py
from django.views.generic.list import ListView
class ProductsView(ListView):
model = Product
paginate_by = 2
context_object_name = 'products'
template_name = 'product.html'
ordering = ['title']Following the post by thepylot1 this is a template for the list view:
templates/product_list.html
<div class="container">
<div class="row infinite-container">
{% for product in products %}
<div class="col-md-6 infinite-item">
<div class="card mb-4 shadow-sm">
<div class="card-body">
<h5>{{product.title}}</h5>
<p class="card-text">
{{product.description}}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}"></a>
{% endif %}
</div>
<script src="/static/js/jquery-2.2.4.min.js"></script>
<script src="/static/js/jquery.waypoints.min.js"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
handler: function(direction) {},
offset: 'bottom-in-view',
onBeforePageLoad: function () {$('.spinner-border').show();},
onAfterPageLoad: function () {$('.spinner-border').hide();}
});
</script>The js import here is all from Waypoints and works. But it return the “normal” pagination. If I add a DjangoFilter2 this code not work with it. You need to edit the get parameters of the url.
The important parts are:
- .infinite-more-link is matching the “Next Page” url for the pagination
- .infinite-item is a selector string for the singolar item in the list
So for the filter to work we need to change the infinite-more-link link with the parameters of the filter.
Adding my stuff
We need to create a new tag for add or edit the get parameters of the url.
templatetags/app_tags.py
from django import template
register = template.Library()
@register.simple_tag
def url_replace_diff(request, field, value):
"""
Give a field and a value and it's update the post parameter for the url accordly
"""
dict_ = request.GET.copy()
dict_[field] = value
return dict_.urlencode()So you need to change the template like this:
templates/product_list.html
<div class="container">
<div class="row infinite-container">
{% for product in products %}
<div class="col-md-6 infinite-item">
<div class="card mb-4 shadow-sm">
<div class="card-body">
<h5>{{product.title}}</h5>
<p class="card-text">
{{product.description}}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% if page_obj.has_next %}
{% load app_tags %}
<a class="infinite-more-link" href="?{% url_replace_diff request 'page' page_obj.next_page_number %}"></a>
{% endif %}
</div>
<script src="/static/js/jquery-2.2.4.min.js"></script>
<script src="/static/js/jquery.waypoints.min.js"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
handler: function(direction) {},
offset: 'bottom-in-view',
onBeforePageLoad: function () {$('.spinner-border').show();},
onAfterPageLoad: function () {$('.spinner-border').hide();}
});
</script>I change the .infinite-more-link url with the new tag for edit the parameters of the filter. In this way you can have infinite scrolling with Django Filter and Django Pagination.
This is the easy way to do it. Or at least it’s the easiest way I can find.
If you can find a better way to do it, please let me know (tweet, email, post with webmention, …) thanks.
This post is part of the Django Tricks series
- Django Rest Framework: Multiple post
- Make a Excel Django combo
- Django With Barcode and Qrcode
- Django Return Pdf With Reportlab
- Django List View With Show More
- Message and Allert With Django and Boostrap
- Csv From Django
- Django Generate Barcode With Reportlab
- Add Minor Things to Django for templating
- Htmx Django and Django Table2
Reference this post
Please reference this post with a link to this page. I prefer to be called Fundor333 (he/him) or Fundor333' Blog.
Comments
To reply to this post, you can send a Webmention or you can toot me at [email protected]