Автоматическая пагинация на Django
Проблема такая: отображаются дублирующие опубликованные посты при автоматической пагинации, что, естественно, некорректно. Можно со страницы home удалить блочный контейнер и тогда пагинация будет появляется с шаблона home_list, но в таком случае пропадает возможность удалять свои же опубликованные посты. Постраничная пагинация для меня это прошлый век, поэтому пытаюсь реализовать автоматическую пагинацию, работает, но дублируются посты. Что я не досмотрел или где допустил ошибку?
views:
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
def load_posts(request):
# Получаем номер страницы из запроса
page_number = request.GET.get('page', 1) # Устанавливаем значение по умолчанию на 1
# Получаем ID пользователей, на которых подписан текущий пользователь
subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)
# Получаем все посты, на которых подписан текущий пользователь или которые он написал
all_posts = Userpublication.objects.filter(Q(author__in=subscribed_user_ids) | Q(author=request.user))
# Создаем объект Paginator
paginator = Paginator(all_posts, 5) # 5 постов на страницу
try:
# Получаем объекты для текущей страницы
current_page_posts = paginator.page(page_number)
except PageNotAnInteger:
# Если номер страницы не является целым числом, показываем первую страницу
current_page_posts = paginator.page(1)
except EmptyPage:
# Если номер страницы находится за пределами допустимого диапазона, возвращаем пустой ответ
return JsonResponse({'posts_html': '', 'next_page_url': None})
# Рендерим HTML с постами текущей страницы
posts_html = render_to_string('****/home_list.html', {'posts': current_page_posts})
# Получаем URL для следующей страницы, если она существует
next_page_url = None
if current_page_posts.has_next():
next_page_url = f"{reverse('load_posts')}?page={current_page_posts.next_page_number()}"
# Возвращаем JSON-ответ с HTML и URL следующей страницы
return JsonResponse({'posts_html': posts_html, 'next_page_url': next_page_url})
urls:
path('load-posts/', views.load_posts, name='load_posts'),
home.html:
<div id="post_contenter">
{% for post in post_lists|slice:":5" %}
<div class="post_content" id="post_content"> <!-- Добавляем идентификатор 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 '****/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">Редактировать</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">Удалить запись</a></span>
{% endif %}
<span><a href="" class="post_user_complain">Пожаловаться</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">
<!-- Уникальный идентификатор для каждого поста -->
<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>
<!-- Уникальный идентификатор для каждой формы комментария -->
<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="Написать комментарий..." required></textarea>
<button type="submit" class="img_sbmt"></button>
</form>
</div>
<!-- Отображение всех комментариев -->
{% 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 '****/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>Ответить</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">редактировать</a>
<a href="#" onclick="saveComment(event, {{ comment.id }})" class="save_comment_link" style="display: none;">Сохранить изменения</a>
</span>
<span class="delete_comment_user"><a href="{% url 'delete_comment' comment_id=comment.id %}">удалить</a></span>
{% endif %}
</div>
</div>
{% if not forloop.last %}
<!-- Если текущий комментарий не последний, добавляем разделитель -->
<hr class="solid_bottom">
{% endif %}
<span class="massage_save_comment_error"></span> <!-- Сообщение об ошибке -->
<span id="save-message-{{ comment.id }}" class="massage_save_comment"></span> <!-- Сообщение о сохранении -->
</div>
{% endfor %}
<br>
</div>
{% endfor %}
</div>
<!-- Пагинация -->
<div id="loading" class="pagination_pages" data-page="2"></div>
</div>
<script>
$(document).ready(function(){
var nextPageUrl = '/load-posts/'; // Используем URL для загрузки постов
function loadMorePosts() {
// Показываем элемент загрузки
//$('#loading').text('Загрузка...');
// Выполняем GET запрос к серверу
$.get(nextPageUrl, function(data) {
// Скрываем элемент загрузки
//$('#loading').text('Загрузить еще');
// Добавляем HTML с постами в конец контейнера
$('#post_contenter').append(data.posts_html);
// Обновляем URL следующей страницы
nextPageUrl = data.next_page_url;
}).fail(function() {
// Обрабатываем ошибку запроса, если она произошла
console.error('Ошибка при загрузке постов');
// Скрываем элемент загрузки
$('#loading').hide();
});
}
// Обработчик события прокрутки страницы
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() >= $(document).height()) {
// Вызываем функцию загрузки дополнительных постов
loadMorePosts();
}
});
// Инициализация загрузки первой страницы постов при загрузке страницы
loadMorePosts();
});
</script>
home_list.html:
<!-- ****/home_list.html -->
{% load humanize %}
{% load static %}
{% block content %}
{% if posts %}
<div class="post-list">
{% for post in posts %}
<div class="post_content" id="post_content"> <!-- Добавляем идентификатор 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 '****/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">Редактировать</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">Удалить запись</a></span>
{% endif %}
<span><a href="" class="post_user_complain">Пожаловаться</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">
<!-- Уникальный идентификатор для каждого поста -->
<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>
<!-- Уникальный идентификатор для каждой формы комментария -->
<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="Написать комментарий..." required></textarea>
<button type="submit" class="img_sbmt"></button>
</form>
</div>
<!-- Отображение всех комментариев -->
{% 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 '****/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>Ответить</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">редактировать</a>
<a href="#" onclick="saveComment(event, {{ comment.id }})" class="save_comment_link" style="display: none;">Сохранить изменения</a>
</span>
<span class="delete_comment_user"><a href="{% url 'delete_comment' comment_id=comment.id %}">удалить</a></span>
{% endif %}
</div>
</div>
{% if not forloop.last %}
<!-- Если текущий комментарий не последний, добавляем разделитель -->
<hr class="solid_bottom">
{% endif %}
<span class="massage_save_comment_error"></span> <!-- Сообщение об ошибке -->
<span id="save-message-{{ comment.id }}" class="massage_save_comment"></span> <!-- Сообщение о сохранении -->
</div>
{% endfor %}
<br>
</div>
{% endfor %}
</div>
{% else %}
<p>Пока нет постов для отображения.</p>
{% endif %}
{% endblock %}