FILter Class 具有分页的基于视图的 ListView

FIlter Class Based View ListView that has pagination

我正在尝试从具有过滤和分页功能的 Class 视图创建 ListView

我能够按我的意愿显示 table 和分页,这为我提供了我需要显示的所有发票的基本列表:

但我无法进行过滤,据我所知,我需要覆盖“get_queryset”方法,这将 return 一个查询集,(在这种情况下称为"invoices_filtered_list") 但是我不知道我应该如何在 .html 页面中呈现它,这样它就会有我应该在其中键入的文本框。

这些是我的文件:

views.py

from django.views.generic import (TemplateView, ListView)
from .models import WoodhistAzolveInvoices
from .filters import WoodhistAzolveInvoicesFilter


class InvoicesListView(ListView):
    model = WoodhistAzolveInvoices
    template_name = 'home.html'
    context_object_name = 'invoices'
    ordering = ['suppliername', 'invoicenumber']
    paginate_by = 50

    def get_queryset(self):
        qs = self.model.objects.all()
        invoices_filtered_list = WoodhistAzolveInvoicesFilter(self.request.GET, queryset=qs)
        return invoices_filtered_list.qs

urls.py

from django.urls import path
from .views import InvoicesListView

app_name = 'web'

urlpatterns = [
    path('', InvoicesListView.as_view(), name='home'),
]

filters.py

import django_filters
from .models import *

class WoodhistAzolveInvoicesFilter(django_filters.FilterSet):
    class Meta:
        model = WoodhistAzolveInvoices
        fields = ['suppliername']

models.py

from django.db import models


class WoodhistAzolveInvoices(models.Model):
    docid = models.CharField(db_column='DocId', primary_key=True, max_length=50)  # Field name made lowercase.
    supplierreference = models.CharField(db_column='SupplierReference', max_length=50, blank=True, null=True)  # Field name made lowercase.
    suppliername = models.CharField(db_column='SupplierName', max_length=100, blank=True, null=True)  # Field name made lowercase.
    invoicenumber = models.CharField(db_column='InvoiceNumber', max_length=50, blank=True, null=True)  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'WoodHist_Azolve_Invoices'

home.html

{% extends "base.html" %}

{% block title %} base title {% endblock title %}


{% block content %}
<h1> azolve home </h1>
<div class="row">
  <div class="col">
    <div class="card card-body">
      <form method="get">
        {{ invoices_filtered_list.form }}
        <button class="btn btn-primary" type="submit">Search</button>
      </form>

    </div>
  </div>
</div>


<table id="myTable1" class="table table-striped table-bordered" style="width:100%">
  <thead>
  <tr>
    <th scope="col">Supplier Name</th>
    <th scope="col">Invoice Number</th>
    <th scope="col">Reference</th>
  </tr>
  </thead>
  <tbody>
  {% for datarow in invoices %}
  <tr>
    <td>{{datarow.suppliername}}</td>
    <td>{{datarow.invoicenumber}}</td>
    <td>{{datarow.supplierreference}}</td>
  </tr>
  {% endfor %}
  {% if is_paginated %}
    {% if page_obj.has_previous %}
      <a class="btn btn-outline-info" href="?page=1">First</a>
      <a class="btn btn-outline-info" href="?page={{ page_obj.previous_page_number}}">Previous</a>
    {% endif %}

  {% for num in page_obj.paginator.page_range %}
    {% if page_obj.number == num %}
      <a class="btn btn-info" href="?page={{ num }}"> {{ num }}</a>
    {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
      <a class="btn btn-outline-info" href="?page={{ num }}"> {{ num }}</a>
    {% endif %}
  {% endfor %}

    {% if page_obj.has_next %}
    <a class="btn btn-outline-info" href="?page={{ page_obj.next_page_number }}">Next</a>
    <a class="btn btn-outline-info" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
    {% endif %}

  {% endif %}
  </tbody>
</table>
{% endblock content %}

如果值得注意,我正在使用包“django_filters”和 Django 3.2.4

您希望同时进行过滤和分页。

您需要进行分页以保留您的 querystrings 然后您可以同时拥有它们。因为当您单击下一页时,您的 querystring 将像这样 .../?page=page_number 所以您的过滤将消失。​​

你可以这样做:

  1. 在您的应用程序目录中创建一个名为 templatetags.

    的文件夹
  2. 在 templatetags 文件夹中创建一个名为 pagination_tags.py(名称由您决定)的文件。

    # Your template tag in app_name/templatetags/pagination_tags.py
    from django import template
    from urllib.parse import urlencode
    
    
    register = template.Library()
    
    @register.simple_tag
    def url_replace (request, field, value):
        dict_ = request.GET.copy()
        dict_[field] = value
    
        return dict_.urlencode()   
    
  3. 创建模板标签后,将其加载到 html 页面并使用。

    {% load pagination_tags %}
    
    {% if is_paginated %}
    <nav aria-label="Page navigation example" class="d-flex justify-content-center pt-3">
      <ul class="pagination">
        {% if page_obj.has_previous and page_obj.number != 2 %}
        <li class="page-item"><a class="page-link text-dark" href="?{% url_replace request 'page' 1 %}" tabindex="-1" aria-disabled="true">First Page</a></li>
        {% endif %}
        {% if page_obj.has_previous %}
        <li class="page-item"><a class="page-link text-dark" href="?{% url_replace request 'page' page_obj.previous_page_number %}">{{ page_obj.previous_page_number }}</a></li>
        {% endif %}
        <li class="page-item disabled"><a class="page-link" href="#">{{ page_obj.number }}</a></li>
        {% if page_obj.has_next %}
        <li class="page-item"><a class="page-link text-dark" href="?{% url_replace request 'page' page_obj.next_page_number %}">{{ page_obj.next_page_number }}</a></li>
        {% endif %}
        {% if page_obj.paginator.num_pages != page_obj.number and page_obj.paginator.num_pages != page_obj.next_page_number %}
        <li class="page-item"><a class="page-link text-dark" href="?{% url_replace request 'page' page_obj.paginator.num_pages %}">Last Page</a></li>
        {% endif %}
      </ul>
    </nav>
    {% endif %}  
    
  4. 而你的ListView应该换成FilterView

    from django_filters.views import FilterView
    from .models import WoodhistAzolveInvoices
    from .filters import WoodhistAzolveInvoicesFilter
    
    
    class InvoicesListView(FilterView):
        model = WoodhistAzolveInvoices
        template_name = "home.html"
        filterset_class = WoodhistAzolveInvoicesFilter
        context_object_name = 'invoices'
        ordering = ['suppliername', 'invoicenumber']
        paginate_by = 50