Skip to content

Instantly share code, notes, and snippets.

@nicholaskajoh
Last active November 27, 2023 10:01
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save nicholaskajoh/ae85bb836f2a6254244c847b962095d4 to your computer and use it in GitHub Desktop.
Save nicholaskajoh/ae85bb836f2a6254244c847b962095d4 to your computer and use it in GitHub Desktop.
Lazy load your content with Django and jQuery
<html>
<head>
<script type="text/javascript">
// A CSRF token is required when making post requests in Django
// To be used for making AJAX requests in script.js
window.CSRF_TOKEN = "{{ csrf_token }}";
</script>
</head>
<body>
<h2>My Blog Posts</h2>
<div id="posts">
{% include 'myapp/posts.html' %}
</div>
<div><a id="lazyLoadLink" href="javascript:void(0);" data-page="2">Load More Posts</a></div>
</body>
</html>
from __future__ import unicode_literals
from django.db import models
class Post(models.Model):
title = models.CharField()
content = models.TextField()
{% for post in posts %}
<div>
<h4>{{ post.title }}</h4>
<p>{{ post.content }}</p>
</div>
{% endfor %}
(function($) {
$('#lazyLoadLink').on('click', function() {
var link = $(this);
var page = link.data('page');
$.ajax({
type: 'post',
url: '/lazy_load_posts/',
data: {
'page': page,
'csrfmiddlewaretoken': window.CSRF_TOKEN // from index.html
},
success: function(data) {
// if there are still more pages to load,
// add 1 to the "Load More Posts" link's page data attribute
// else hide the link
if (data.has_next) {
link.data('page', page+1);
} else {
link.hide();
}
// append html to the posts div
$('#posts').append(data.posts_html);
},
error: function(xhr, status, error) {
// shit happens friends!
}
});
});
}(jQuery));
from myapp import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^lazy_load_posts/$', views.lazy_load_posts, name='lazy_load_posts'),
]
from django.shortcuts import render
from myapp.models import Post
from django.template import loader
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.http import JsonResponse
def index(request):
posts = Post.objects.all()[:5]
return render(request, 'myapp/index.html', {'posts': posts})
def lazy_load_posts(request):
page = request.POST.get('page')
posts = Post.objects.all()
# use Django's pagination
# https://docs.djangoproject.com/en/dev/topics/pagination/
results_per_page = 5
paginator = Paginator(posts, results_per_page)
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(2)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
# build a html posts list with the paginated posts
posts_html = loader.render_to_string('myapp/posts.html', {'posts': posts})
# package output data and return it as a JSON object
output_data = {'posts_html': posts_html, 'has_next': posts.has_next()}
return JsonResponse(output_data)
@marramsaleh
Copy link

how you show the data in the template , imean i can access the posts in the template

@onoyimaobia
Copy link

this code is not working
how does the javascript code fetch more form db when one click on load more
load more post does not call any data from database
please review your code or send demo

@octavioamu
Copy link

octavioamu commented Sep 12, 2018

@onoyimaobia

this code is not working
how does the javascript code fetch more form db when one click on load more
load more post does not call any data from database
please review your code or send demo

@onoyimaobia take you time look at the code and read https://blog.devcenter.co/lazy-load-your-content-with-django-and-jquery-1bc5dea69f84 and you will understand, the code is working and front end js never fetch data from db is calling an endopoint and that endoind run lazy_load_posts

@nenadzero
Copy link

this code is not working
how does the javascript code fetch more form db when one click on load more
load more post does not call any data from database
please review your code or send demo
(script.js) line 23:
change $('#div') to $('#posts')

@nicholaskajoh
Copy link
Author

Thanks @nenadzero. Updated!

@nenadzero
Copy link

I also added:

if request.user.is_authenticated:
        user = request.user
    else:
        user = None

before line 27 views.py
and change line 27 to:
posts_html = loader.render_to_string('myapp/posts.html', {'user': user, 'posts': posts})
because we must have user info in template
example:

{% for post in posts %}
{% if user in post.likes.all %} 
<button> Unlike </button>
{ % else %} 
<button> Like </button>
{% endif %}
{% endfor %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment