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
所以您的过滤将消失。
你可以这样做:
在您的应用程序目录中创建一个名为 templatetags
.
的文件夹
在 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()
创建模板标签后,将其加载到 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 %}
而你的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
我正在尝试从具有过滤和分页功能的 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
所以您的过滤将消失。
你可以这样做:
在您的应用程序目录中创建一个名为
的文件夹templatetags
.在 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()
创建模板标签后,将其加载到 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 %}
而你的
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