使用 Django Listview 在过滤查询集中分页

Pagination in filtered queryset using Django Listview

我在尝试过滤查询集时在通用 ListView 中使用分页时遇到问题。过滤器工作正常,但问题是当尝试访问不是第一个页面时,出现错误:无效页面 (2):该页面不包含任何结果

如果我删除所有分页会怎样?你会推荐什么? 该模板的目标是在列表中显示日期过滤的销售以及客户过滤器

这是我的代码:

class ListSales(LoginRequiredMixin, ListView):
    template_name = "sales/list.html"
    context_object_name = 'sales'
    login_url = reverse_lazy('users_app:user-login')
    paginate_by = 5

    def get_queryset(self):
        client = self.request.GET.get("clientselect", "")
        date1 = self.request.GET.get("date1", '')
        date2 = self.request.GET.get("date2", '')

        if date1 == '':
            date1 = datetime.date.today()
        if date2 == '':
            date2 = datetime.date.today()
        queryset = Sale.objects.get_sales_list(date1, date2, client)
        return queryset

这是我的模板:

{% extends "panel.html" %}

{% load  static %}

{% block panel-content %}

<div class="grid-x medium-10">
    <h3 class="cell medium-12" style="text-align: center;">Ventas</h3> 
    <div class="cell medium-12">&nbsp </div>
    <form class="cell medium-10" method="GET">{% csrf_token %}
        <div class="input-group grid-x medium-12">
            
            <div class="input-group cell medium-3 grid-x">
                <label class="cell medium-12">Desde:</label>
                <span class="input-group-label"><i class="fi-calendar"></i></span>
                <input type="date" id="date1" name="date1" class="input-group-field" type="date">
                
            </div>
            &nbsp&nbsp&nbsp
            <div class="input-group cell medium-3 grid-x">
                <label class="cell medium-12">Hasta:</label>
                <span class="input-group-label"><i class="fi-calendar"></i></span>
                <input type="date" id="date2" name="date2" class="input-group-field" type="date">
                
            </div>
            <div class="cell medium-1"></div>
            <div class="input-group cell medium-3 grid-x">
                <label class="cell medium-12">Cliente:</label>
                <span class="input-group-label"><i class="fi-torso"></i></span>
                <select id="clientselect" name="clientselect" class="input-group-field">
                    <option value="0" id="option0" name="option0" >Todos</option>
                    <option value="-1" id="option-1" name="option-1" >Sin Cliente</option>
                    {% for client in clients %}
                    <option value="{{client.pk}}" id="option{{client.pk}}" name="option{{client.pk}}" >{{client.full_name}}</option>
                    {% endfor %}
                </select>
                
            </div>
            <div class="cell medium-1"></div>
            <div class="cell medium-1">
                <button type="submit" class="button cell medium-4"><i class="fi-filter"></i>&nbsp Filtrar</button>
            </div>
            
        </div>
    </form>
    <div class="cell medium-12"> </div>
    <table class="cell medium-12">
        <thead>
            <th>Fecha</th>
            <th>Nro Factura</th>
            <th>Cliente</a></th>            
            <th>Monto</th>
            <th>Acciones</th>
         
        </thead>
        <tbody>
          {% for sale in sales %}
            <tr>
                
              <td>{{ sale.show_date }}</td>
              <td>{{ sale.invoice_number }}</td>
              <td>{{ sale.client.full_name }}</td>
              <td>${{ sale.amount_with_discount}}</td>
              <td>
              <div class="button-group">
                <a href="#" class="button warning tiny" data-toggle="modalView{{sale.pk}}"><i class="fi-eye"></i></a>
                
            </td>
              </div>

            </tr>

        
            <div class="tiny reveal" id="modalView{{sale.pk}}" style="background-color:rgb(51,51,51);" data-reveal data-close-on-click="true" data-animation-in="spin-in" data-animation-out="spin-out">
                <h4 class="cell" style="text-align: center;">Detalle de Venta</h4>
    
                
              </div>


          {% endfor %}
        </tbody>
    </table>    

    {% if is_paginated %}
    <ul class="pagination cell medium-12">
      {% if page_obj.has_previous %}
      <li><a href="?page={{ page_obj.previous_page_number }}" style="color: wheat;">&laquo;</a></li>
      {% else %}
      <li class="disabled"><span style="color: wheat;">&laquo;</span></li>
      {% endif %} {% for i in paginator.page_range %} {% if page_obj.number == i %}
      <li class="active">
        <span style="color: wheat;">{{ i }} <span class="sr-only">(actual)</span></span>
      </li>
      {% else %}
      <li><a href="?page={{ i }}" style="color: wheat;">{{ i }}</a></li>
      {% endif %} {% endfor %} {% if page_obj.has_next %}
      <li><a href="?page={{ page_obj.next_page_number }}" style="color: wheat;">&raquo;</a></li>
      {% else %}
      <li class="disabled"><span style="color: wheat;">&raquo;</span></li>
      {% endif %}
    </ul>
    {% endif %}

  </div>

  
  
  {% endblock panel-content %}

失败的原因是如果您单击下一页,则查询字符串的其余部分(搜索参数)不会传递给以下请求。

您可以对查询字符串的其余部分进行编码:

class ListSales(LoginRequiredMixin, ListView):
    # …
    
    def <strong>urencode_filter</strong>(self):
        qd = self.request.GET.copy()
        qd.pop(self.page_kwarg, None)
        return qd.urencode()

在指向其他页面的链接中,然后添加 urlencode_filter() 值:

<li><a href="?page={{ page_obj.previous_page_number }}<strong>&amp;{{ view.urlencode_filter }}</strong>" style="color: wheat;">&laquo;</a></li>

并使用指向上一页、下一页和任意页面的 所有 链接来执行此操作。

您还可以创建一个自定义 param_replace 模板标记来仅更新一个查询参数并保留所有其他参数:

<a href="?{% param_replace page=page_obj.previous_page_number %}">&laquo;</a>

详情见:https://www.caktusgroup.com/blog/2018/10/18/filtering-and-pagination-django/ and