I need help solving a problem with automatic pagination. When automatic pagination occurs from the home_list.html template to the home.html template, all functions of the template stop working, even though the template itself is paginated correctly. The functionality stops working after pagination, namely: “edit” and “delete” the published post, “Add comment”, “Edit comment”, “Save edited comment”, “Delete comment”.
In the home.html template, these functions work in the {% for post in post_lists %} loop, but after automatic pagination from the home_list.html template in the {% for post in posts %} loop, these functions do not work. How can I fix this?
home.html
<div id="post_contenter">
{% for post in post_lists %}
<div class="post_content" id="post_content"> <!-- Add identifier post_content -->
<div class="post_header">
<div class="post_user_avatar">
{% if post.author.avatar %}
<img style="width:50px; height: 50px;" src="{{ post.author.avatar.url }}" class="user-picture-small">
{% else %}
<img style="width:50px; height: 50px;" src="{% static 'twippie/img/avatar.png' %}" class="card_user_picture_small">
{% endif %}
</div>
<div class="post_user_info">
<div class="post_user_fullname"><a href="{% url 'user:profile_username' post.author.username %}" class="post_user_fullname_style">{{ post.author.first_name }} {{ post.author.last_name }}</a></div>
<div class="post_user_username"><a href="{{ user_profile.username }}" class="post_user_nickname_style">@{{ post.author }}</a>
{% if post.author.verification %}
<span class="verified_user_small"></span>
{% endif %}
</div>
<div class="post_user_date"><a href="{{ post.get_absolute_url }}" class="post_user_date_style">{{ post.time_create }} {{ post.time_create|naturaltime }}</a></div>
</div>
</div>
<div class="post_user_more">
<div class="dropdown dropbtn" style="float:right;">
<div class="dropdown-content">
{% if request.user == post.author %}
<span><a href="{% url 'edit_post' post_slug=post.slug %}" class="post_user_edit">Edit</a></span>
{% endif %}
{% if user.is_authenticated and user == post.author %}
<span><a href="{% url 'delete_post' post_slug=post.slug %}" class="post_user_delete">Delete post</a></span>
{% endif %}
<span><a href="" class="post_user_complain">Report</a></span>
</div>
</div>
</div>
<div class="post_user_content">
{{ post.content }}
</div>
<div class="post_user_action">
<div class="post_user_liked_post">
{% if liked_by_current_user %}
<div class="unlike-button" id="unlike-button-{{ post.id }}" data-post-id="{{ post.id }}"></div>
{% else %}
<div class="like-button" id="like-button-{{ post.id }}" data-post-id="{{ post.id }}"></div>
{% endif %}
<div class="count_likevalue">
<span class="like-count-value like_count_style" id="like-count-{{ post.id }}" data-post-id="{{ post.id }}">{{ like_count }}</span>
</div>
</div>
<div class="containercomment_post">
<!-- Unique identifier for each post -->
<div class="post_user_comment_post" data-post-id="{{ post.id }}">
<span class="count_comment">{{ post.comments.count }}</span>
</div>
</div>
<div class="post_user_share_post"></div>
<div class="post_user_views_post">
<div class="post_user_views_post_count"><span class="post_user_views_post_count_style">125025</span></div>
</div>
</div>
<!-- Unique identifier for each comment form -->
<div class="comment-form hidden" data-post-id="{{ post.id }}">
<hr>
<form action="{% url 'add_comment' post_id=post.id %}" method="post">
{% csrf_token %}
<textarea name="content" class="user_comment_style" placeholder="Write a comment..." required></textarea>
<button type="submit" class="img_sbmt"></button>
</form>
</div>
<!-- Display all comments -->
{% for comment in post.comments.all %}
<div class="comment-container">
<div class="comment_post">
{% if comment.author.avatar %}
<img src="{{ comment.author.avatar.url }}" class="comment_author_img_style">
{% else %}
<img src="{% static 'twippie/img/avatar.png' %}" class="comment_author_img_style">
{% endif %}
<div class="comment_author"><a href="{% url 'user:profile_username' username=comment.author.username %}">{{ comment.author.first_name }}</a></div>
<div class="comment_content" id="comment-content-{{ comment.id }}">{{ comment.content }}</div>
<div class="comment_time">{{ comment.created_at }}
<!--<span class="answer_comment_user"><a>Reply</a></span>-->
{% if comment.author == request.user %}
<span id="edit-actions-{{ comment.id }}" class="edit_comment_user">
<a href="#" onclick="editComment({{ comment.id }})" class="edit_comment_link">edit</a>
<a href="#" onclick="saveComment(event, {{ comment.id }})" class="save_comment_link" style="display: none;">Save changes</a>
</span>
<span class="delete_comment_user"><a href="{% url 'delete_comment' comment_id=comment.id %}">delete</a></span>
{% endif %}
</div>
</div>
{% if not forloop.last %}
<!-- If the current comment is not the last one, add a separator -->
<hr class="solid_bottom">
{% endif %}
<span class="massage_save_comment_error"></span> <!-- Error message -->
<span id="save-message-{{ comment.id }}" class="massage_save_comment"></span> <!-- Save message -->
</div>
{% endfor %}
<br>
</div>
{% endfor %}
<div id="pagination-loader" class="pagination_pages" data-page="1"></div>
</div>
<script>
$(document).ready(function(){
var loadedPage = 1; // Variable to store the loaded page number
// Function to load the next batch of posts
function loadNextPage() {
// Perform an AJAX request to the server
var nextPageUrl = '/load-posts/?page=' + (loadedPage + 1);
console.log("Next page URL:", nextPageUrl);
$.ajax({
url: nextPageUrl,
type: 'GET',
dataType: 'json',
success: function(response) {
console.log("Response from server:", response);
// Check if there is data about posts in the JSON response
if (response.posts) {
// Add HTML with posts to the end of the container
$('#post_contenter').append(response.html_posts);
// Check if there are more posts on the next page
if (response.next_page_url) {
// Increase the value of the loadedPage variable
loadedPage++;
} else {
// If there is no next page, hide the loading indicator
$('#pagination-loader').hide();
}
} else {
// If there is no data about posts, display an error message
console.error('Error loading posts: data about posts is missing in the JSON response');
}
},
error: function(jqXHR, textStatus, errorThrown) {
// Handle the error if it occurred during the request
console.error('Error loading posts:', textStatus, errorThrown);
}
});
}
// Event handler for scrolling the page
$(window).on('scroll', function() {
// Get the current scroll position
var scrollPosition = $(window).scrollTop();
// Get the height of the browser window
var windowHeight = $(window).height();
// Get the height of the entire document
var documentHeight = $(document).height();
// If the user has scrolled to the end of the page
if (scrollPosition + windowHeight >= documentHeight) {
// Check if the loading indicator is visible
if ($('#pagination-loader').is(':visible')) {
// Load the next batch of posts
loadNextPage();
}
}
});
// Check if the first page of posts needs to be loaded when the page is loaded
if($(window).scrollTop() + $(window).height() == $(document).height()) {
loadNextPage();
}
});
</script>
<style>
.hidden {
display: none;
}
</style>
home_list.html:
{% load humanize %}
{% load static %}
{% block content %}
{% if posts %}
<div class="post-list">
{% for post in posts %}
{% if not forloop.first and post.author != request.user %}
<div class="post_content" id="post_content"> <!-- Add identifier post_content -->
<div class="post_header">
<div class="post_user_avatar">
{% if post.author.avatar %}
<img style="width:50px; height: 50px;" src="{{ post.author.avatar.url }}" class="user-picture-small">
{% else %}
<img style="width:50px; height: 50px;" src="{% static 'twippie/img/avatar.png' %}" class="card_user_picture_small">
{% endif %}
</div>
<div class="post_user_info">
<div class="post_user_fullname"><a href="{% url 'user:profile_username' post.author.username %}" class="post_user_fullname_style">{{ post.author.first_name }} {{ post.author.last_name }}</a></div>
<div class="post_user_username"><a href="{{ user_profile.username }}" class="post_user_nickname_style">@{{ post.author }}</a>
{% if post.author.verification %}
<span class="verified_user_small"></span>
{% endif %}
</div>
<div class="post_user_date"><a href="{{ post.get_absolute_url }}" class="post_user_date_style">{{ post.time_create }} {{ post.time_create|naturaltime }}</a></div>
</div>
</div>
<div class="post_user_more">
<div class="dropdown dropbtn" style="float:right;">
<div class="dropdown-content">
{% if request.user == post.author %}
<span><a href="{% url 'edit_post' post_slug=post.slug %}" class="post_user_edit">Edit</a></span>
{% endif %}
{% if user.is_authenticated and user == post.author %}
<span><a href="{% url 'delete_post' post_slug=post.slug %}" class="post_user_delete">Delete post</a></span>
{% endif %}
<span><a href="" class="post_user_complain">Report</a></span>
</div>
</div>
</div>
<div class="post_user_content">
{{ post.content }}
</div>
<div class="post_user_action">
<div class="post_user_liked_post">
{% if liked_by_current_user %}
<div class="unlike-button" id="unlike-button-{{ post.id }}" data-post-id="{{ post.id }}"></div>
{% else %}
<div class="like-button" id="like-button-{{ post.id }}" data-post-id="{{ post.id }}"></div>
{% endif %}
<div class="count_likevalue">
<span class="like-count-value like_count_style" id="like-count-{{ post.id }}" data-post-id="{{ post.id }}">{{ like_count }}</span>
</div>
</div>
<div class="containercomment_post">
<!-- Unique identifier for each post -->
<div class="post_user_comment_post" data-post-id="{{ post.id }}">
<span class="count_comment">{{ post.comments.count }}</span>
</div>
</div>
<div class="post_user_share_post"></div>
<div class="post_user_views_post">
<div class="post_user_views_post_count"><span class="post_user_views_post_count_style">125025</span></div>
</div>
</div>
<!-- Unique identifier for each comment form -->
<div class="comment-form hidden" data-post-id="{{ post.id }}">
<hr>
<form action="{% url 'add_comment' post_id=post.id %}" method="post">
{% csrf_token %}
<textarea name="content" class="user_comment_style" placeholder="Write a comment..." required></textarea>
<button type="submit" class="img_sbmt"></button>
</form>
</div>
<!-- Display all comments -->
{% for comment in post.comments.all %}
<div class="comment-container">
<div class="comment_post">
{% if comment.author.avatar %}
<img src="{{ comment.author.avatar.url }}" class="comment_author_img_style">
{% else %}
<img src="{% static 'twippie/img/avatar.png' %}" class="comment_author_img_style">
{% endif %}
<div class="comment_author"><a href="{% url 'user:profile_username' username=comment.author.username %}">{{ comment.author.first_name }}</a></div>
<div class="comment_content" id="comment-content-{{ comment.id }}">{{ comment.content }}</div>
<div class="comment_time">{{ comment.created_at }}
<!--<span class="answer_comment_user"><a>Reply</a></span>-->
{% if comment.author == request.user %}
<span id="edit-actions-{{ comment.id }}" class="edit_comment_user">
<a href="#" onclick="editComment({{ comment.id }})" class="edit_comment_link">edit</a>
<a href="#" onclick="saveComment(event, {{ comment.id }})" class="save_comment_link" style="display: none;">Save changes</a>
</span>
<span class="delete_comment_user"><a href="{% url 'delete_comment' comment_id=comment.id %}">delete</a></span>
{% endif %}
</div>
</div>
{% if not forloop.last %}
<!-- If the current comment is not the last one, add a separator -->
<hr class="solid_bottom">
{% endif %}
<span class="massage_save_comment_error"></span> <!-- Error message -->
<span id="save-message-{{ comment.id }}" class="massage_save_comment"></span> <!-- Save message -->
</div>
{% endfor %}
<br>
</div>
{% endif %}
{% endfor %}
</div>
{% else %}
<p>No posts to display yet.</p>
{% endif %}
<style>
.hidden {
display: none;
}
</style>
{% endblock %}
views.py:
from django.shortcuts import render, redirect
from usercreatepost.forms import PostForm
from publication.models import Userpublication
from user.models import ProfileMyapp, Subscription
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.urls import reverse
from django.http import JsonResponse
from django.template.loader import render_to_string
from django.db.models import Q
@login_required
def create_post(request):
form = PostForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('home')
# Get IDs of users subscribed by the current user
subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)
# Get all posts by authors subscribed by the current user
subscribed_posts = Userpublication.objects.filter(author__in=subscribed_user_ids)
# Get all posts by the current user
own_posts = Userpublication.objects.filter(author=request.user)
# Merge post lists
all_posts = (subscribed_posts | own_posts).order_by('-time_create')
# Get page object of posts to display
page_number = request.GET.get('page', 1)
paginator = Paginator(all_posts, 5) # 5 posts per page
try:
page_posts = paginator.page(page_number)
except PageNotAnInteger:
page_posts = paginator.page(1)
except EmptyPage:
page_posts = paginator.page(paginator.num_pages)
context = {'form': form, 'post_lists': page_posts, 'title': 'Myapp | News', 'page_number': page_number}
return render(request, 'myapp/home.html', context)
def load_posts(request):
# Get page number from the request
page_number = request.GET.get('page', 1) # Set default value to 1
# Get IDs of users subscribed by the current user
subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)
# Get all posts subscribed by the current user or authored by them
all_posts = Userpublication.objects.filter(Q(author__in=subscribed_user_ids) | Q(author=request.user)).order_by('-time_create')
# Create a Paginator object
paginator = Paginator(all_posts, 5) # 5 posts per page
try:
# Get objects for the current page
current_page_posts = paginator.page(page_number)
except PageNotAnInteger:
# If page number is not an integer, show the first page
current_page_posts = paginator.page(1)
except EmptyPage:
# If page number is out of range, return an empty response
return JsonResponse({'posts': [], 'next_page_url': None})
# Rendering HTML markup of posts
html_posts = render_to_string('myapp/home_list.html', {'posts': current_page_posts})
# Forming a list of posts to pass to JSON
posts_list = [{'id': post.id, 'content': post.content} for post in current_page_posts]
# Get URL for the next page if it exists
next_page_url = None
if current_page_posts.has_next():
next_page_url = reverse('load_posts') + f'?page={current_page_posts.next_page_number()}'
# Return JSON response with data about the posts, HTML markup, and URL of the next page
return JsonResponse({'posts': posts_list, 'html_posts': html_posts, 'next_page_url': next_page_url})
