在 Django 中使用两个以不同方式格式化的查询集进行分页

Posted

技术标签:

【中文标题】在 Django 中使用两个以不同方式格式化的查询集进行分页【英文标题】:Pagination in Django with two Querysets formatted in different ways 【发布时间】:2019-12-08 09:48:53 【问题描述】:

我想让分页处理以不同方式格式化的两个单独的查询集。第一个查询集较小,永远不会比第一页长。第二个查询集很长,会持续 5 或 6 页。两个查询集的结果内容是一样的,但是我在html模板中的格式不同。

Book 和 PremiumBook 的模型完全相同,只是 PremiumBook 的书籍更多(并且包含 Book 中的所有元素)。

我将包含 views.py 和模板:

def servicesListView(request, category):
    model = Books
    table = Books.objects.filter(category=category)
    values_books = table.filter().values_list("serviceid")
    # remove these observations from next table. My next table is premium and not available to non-authenticated users
    new_table = PremiumBooks.objects.filter(category=category).exclude(bookid__in=values_books)
    new_table = new_table.filter().annotate(price_count=Count('premiumcost__price')).order_by('-price_count')[:60]
    page = request.GET.get('page', 1)
    paginator = Paginator(new_table, 5)
    try:
        new_table = paginator.page(new_table)
    except PageNotAnInteger:
        new_table = paginator.page(1)
    except EmptyPage:
        new_table = paginator.page(paginator.num_pages)
    return render(request, 'services/index.html', 'table': table, 'new_table': new_table)

那么,这是他们的模板:

<main class="ui-book-list"> 
    <div class="results-list grid-view">
        <div class="container">
            <h2>Book list </h2>
            <div class="grid-results-list book-list">
                % for book in table %
                        <div class="record">
                            <div class="content">
                                <h6>
                                     book.easy_desc 
                                </h6>
                                <div class="group">
                                    <div class="category">
                                        <span>Category:</span>  book.category 
                                    </div>
                                    <span class="divider"></span>
                                    <div class="code">
                                        <span>Barcode:</span>  book.code 
                                    </div>
                                </div>
                            </div>
                        </div>
                    </a>
                % empty %
                % endfor %

                % for book in new_table %
                    <div class="premium-user">
                        <div class="record">
                            <div class="content">
                                <div class="premium-tag" onclick="openPremiumModal()"><i class="fas fa-lock"></i>Premium User</div>
                                <a class="link" onclick="openPremiumModal()">
                                    <h6>
                                         book.desc_us 
                                    </h6>
                                </a>
                                <div class="group">
                                    <div class="category ">
                                        <span class="">Category:</span>  book.category 
                                    </div>
                                    <span class="divider"></span>
                                    <div class="code ">
                                        <span class="">Barcode:</span>  book.code 
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                % endfor %

#this is my pagination stuff for one table, not sure how to do it for combined table
                % if new_table.has_other_pages %
                    <ul class="pagination mt-5 pagination-sm justify-content-center">
                        % if new_table.has_previous %
                            <li class="page-item">
                                <a
                                    class="page-link"
                                    href="?page= new_table.previous_page_number % if request.GET.csrfmiddlewaretoken %&csrfmiddlewaretoken= request.GET.csrfmiddlewaretoken % endif %% if request.GET.s %&s= request.GET.s % endif %">
                                    <i class="fa fa-chevron-left" aria-hidden="true"></i>
                                </a>
                            </li>
                        % else %
                            <li class="page-item disabled">
                                <span class="page-link">
                                    <i class="fa fa-chevron-left" aria-hidden="true"></i>
                                </span>
                            </li>
                        % endif %

                        % if new_table.number|add:'-4' > 1 %
                        <li class="page-item">
                            <a class="page-link" href="?page= new_table.number|add:'-5' % if request.GET.csrfmiddlewaretoken %&csrfmiddlewaretoken= request.GET.csrfmiddlewaretoken % endif %% if request.GET.s %&s= request.GET.s % endif %">&hellip;</a>
                        </li>
                        % endif %

                        % for i in new_table.paginator.page_range %
                            % if new_table.number == i %
                                <li class="page-item active">
                                    <span class="page-link"> i  <span class="sr-only">(current)</span></span>
                                </li>
                            % elif i > new_table.number|add:'-5' and i < new_table.number|add:'5' %
                                <li class="page-item">
                                    <a class="page-link" href="?page= i % if request.GET.csrfmiddlewaretoken %&csrfmiddlewaretoken= request.GET.csrfmiddlewaretoken % endif %% if request.GET.s %&s= request.GET.s % endif %"> i </a>
                                </li>
                            % endif %
                        % endfor %

                        % if new_table.paginator.num_pages > new_table.number|add:'4' %
                            <li class="page-item">
                                <a class="page-link" href="?page= new_table.number|add:'5' % if request.GET.csrfmiddlewaretoken %&csrfmiddlewaretoken= request.GET.csrfmiddlewaretoken % endif %% if request.GET.s %&s= request.GET.s % endif %">&hellip;</a>
                            </li>
                        % endif %

                        % if new_table.has_next %
                            <li class="page-item">
                                <a class="page-link" href="?page= new_table.next_page_number % if request.GET.csrfmiddlewaretoken %&csrfmiddlewaretoken= request.GET.csrfmiddlewaretoken % endif %% if request.GET.s %&s= request.GET.s % endif %">
                                    <i class="fa fa-chevron-right" aria-hidden="true"></i>
                                </a>
                            </li>
                        % else %
                            <li class="page-item disabled">
                                <span class="page-link"><i class="fa fa-chevron-right" aria-hidden="true"></i></span>
                            </li>
                        % endif %
                    </ul>
                % endif %
            </div>
        </div>
    </div>
</main>

【问题讨论】:

您能具体说明您希望发生的事情吗? 您想要在您的页面上选择非高级图书列表,但又想为高级图书分页? 我想先列出基础书籍,然后是高级书籍。高级书籍将对其进行锁定,并且只有登录的用户才能访问高级书籍。它将采用不同的格式,因为高级书籍将锁定它们并重定向到登录页面。 拥有一个具有premium 布尔列的Book 模型不是更容易吗?然后在您的列表视图中,您只需按匹配类别过滤书籍 渲染书籍时,如果它们是优质书籍,则添加逻辑以“锁定”它们 【参考方案1】:

你可以有 2 个不同的QuerySets,甚至可以像这样按不同的数量分页

regular_books_query = Books.objects.filter(category=category)  # plus whatever
premium_books_query = Premium.objects.filter(category=category)  # plus whatever

regular_paginator = Paginator(regular_books, 10)
premium_paginator = Paginator(premium_books, 5)

page = request.GET.get('page')

regular_books = regular_paginator.get_page(page)
premium_books = premium_paginator.get_page(page)

return render('template.html', 
    'regular_books': regular_books,
    'premium_books': premium_books
)

Now whenever you go to the next page you will get the next page in both queryset

【讨论】:

以上是关于在 Django 中使用两个以不同方式格式化的查询集进行分页的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spark 以不同的方式解释这两个查询?

在不同的占位符/模板上以不同的方式呈现 Django-CMS 插件

Django:使用 ajax 查询(字符串/Json)时出现格式问题

Django 在模板中使用两个不同的数据集填充表

子查询 django 查询以从对象中获取最大的不同值并返回这些对象

Django 视图:以 JSON 格式返回查询集