Django自动分页问题,如何修复重复帖子?

-1 投票
2 回答
35 浏览
提问于 2025-04-12 04:58

问题是,在自动分页的时候出现了重复的帖子。如果在home.html模板中,循环{% for post in post_lists %}指定输出5个已发布的帖子,那么在自动分页时,这5个已发布的帖子会在home_list.html模板中重复出现,这样就不对了。自动分页本身是正常工作的,可以正确显示所有已发布的帖子。问题只出在前五个已发布的帖子上,它们被重复了,而其他的帖子没有重复,显示也正常。请问该如何解决这个问题呢?

home.html:

{% for post in post_lists %}
<div class="post_content" id="post_content">
<!----code for displaying posts goes here---->
</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;
        console.log("Next page URL:", nextPageUrl);

        $.ajax({
            url: nextPageUrl,
            type: 'GET',
            dataType: 'json',
            success: function(response) {
                console.log("Response from server:", response);

                // Check for post data 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) {
                        // Increment 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 post data, display an error message
                    console.error('Error loading posts: Post data is missing in the JSON response');
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                // Handle the request error if it occurs
                console.error('Error loading posts:', textStatus, errorThrown);
            }
        });
    }

    // Event handler for page scrolling
    $(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>

home_list.html:

{% if posts %}
    <div class="post-list">
        {% for post in posts %}
<div class="post_content" id="post_content">
<!----code for displaying posts goes here---->
</div>
</div>
       {% endfor %}
{% endif %}

views.py:

@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 the IDs of users whom the current user is subscribed to
    subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)

    # Get all posts from authors whom the current user is subscribed to
    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)

    # Combine the lists of posts
    all_posts = (subscribed_posts | own_posts).order_by('-time_create').distinct()

    # Get the page object for displaying posts
    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': 'Twippie | News', 'page_number': page_number}
    return render(request, 'twippie/home.html', context)

@login_required
def load_posts(request):
    # Get the page number from the request
    page_number = request.GET.get('page', 1)  # Default to page 1 if not provided
    
    # Get the IDs of users whom the current user is subscribed to
    subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)
    
    # Get all posts from users whom the current user is subscribed to or posts authored by the current user
    all_posts = Userpublication.objects.filter(Q(author__in=subscribed_user_ids) | Q(author=request.user)).order_by('-time_create').distinct()
    
    # Create a Paginator object
    paginator = Paginator(all_posts, 5)  # 5 posts per page

    try:
        # Get the objects for the current page
        current_page_posts = paginator.page(page_number)
    except PageNotAnInteger:
        # If the page number is not an integer, show the first page
        current_page_posts = paginator.page(1)
    except EmptyPage:
        # If the page is out of range, return an empty response
        return JsonResponse({'posts': [], 'next_page_url': None})
    
    # Render HTML markup for the posts
    html_posts = render_to_string('twippie/home_list.html', {'posts': current_page_posts})
    
    # Form a list of posts to pass to JSON
    posts_list = [{'id': post.id, 'content': post.content} for post in current_page_posts]
    
    # Get the 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 a 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})

2 个回答

0

两个关键点

  1. 你需要根据创建时间来排序,我猜你是在测试,并且在一个循环中创建了帖子,有时候这会导致多个帖子有相同的创建时间。

  2. 这是普通分页器(限制/偏移量)的一个限制,建议使用光标分页器。

在DRF中支持光标分页,使用 rest_framework.pagination.CursorPagination,在 django_paginator_class 中使用它。

0

问题:

{% for post in post_lists %}
<div class="post_content" id="post_content">
<!----  PAGE 1 ALREADY LOADED HERE  ---->
</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;

// HERE YOU LOAD, ALREADY LOADED PAGE AGAIN 

看看代码里的注释。第一页面已经加载完成了。但是你又用JavaScript重新加载了第一页面。这就是问题所在。

回答:

var nextPageUrl = '/load-posts/?page=' + (loadedPage + 1);

撰写回答