16

我开始使用django-tables2(我可以从第一印象强烈推荐),我问自己如何实现列过滤。我没有找到合适的文档,但我确信它在某个地方。

4

4 回答 4

27

答案有点晚,但无论如何......我也找不到任何合适的列过滤文档。有很多方法可以做到:

A. 手动:我添加了一个包含我想过滤的字段的表单,然后在我的视图中执行类似的操作:

  数据 = 模型.MyClass.all()
  form = forms.MyFilterForm(request.GET)
  如果 request.GET.get('field1'):
    数据 = data.filter(field1=request.GET.get('field1') )
  如果 request.GET.get('field2'):
    数据 = data.filter(field2=request.GET.get('field2') )   
  ...
  表 = 表。我的表(数据)

这很好用,但它不是那么干燥,因为它在视图中是硬编码的。

B. 使用 SingleTableView:另一种方法是添加包含表单的 SingleTableView:

从 django_tables2 导入 SingleTableView
类FilteredSingleTableView(SingleTableView):
  def get_table_data(self):
    数据=模型.MyClass.objects.all
    如果 self.request.GET.get('field1'):
      数据 = data.filter(field1=self.request.GET.get('field1') )
    如果 self.request.GET.get('field1'):
      数据 = data.filter(field1=self.request.GET.get('field1') )
    返回数据

    def get_context_data(self, **kwargs):
      context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
      上下文['form'] = forms.MyFilterForm(self.request.user, self.request.GET)
      返回上下文

这更干:)

C. 使用 SingleTableView 和 django_filters:这可能是最干燥的方式 :) 以下是如何做到的:

首先定义一个过滤器:

MyFilter 类(django_filters.FilterSet):
  field1 = django_filters.CharFilter()
  field2 = django_filters.CharFilter()
...

(或者您可以在 Meta 中添加模型过滤器(模型 = MyModel)

现在,像这样创建一个 SingleTableView

类FilteredSingleTableView(SingleTableView):
  def get_table_data(self):
    f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all(), request=self.request)
    返回 f

  def get_context_data(self, **kwargs):
    context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
    f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all(), request=self.request)
    上下文['form'] = f.form
    返回上下文

(可能 f =... 行有问题,但否则我无法使其工作。

最后,您可以像这样从 urls.py 调用 SingleTableView

url(r'^$', views.FilteredSingleTableView.as_view(
    table_class = tables.MyTable,
    模型=模型.MyClass,
    template_name ='mytemplate.html',
    table_pagination={ "per_page":50 } )) ,
    name='filtered_single_table_view'
),

D. 使用泛型类:这是一种更加 DRY 和 django-generic-class-views 的方式!这实际上是C的下一步:只需像这样声明您的 FilteredSingleTableView :

类 FilteredSingleTableView(django_tables2.SingleTableView):
  filter_class = 无

  def get_table_data(self):
    self.filter = self.filter_class(self.request.GET, queryset =super(FilteredSingleTableView, self).get_table_data() )
    返回 self.filter.qs

  def get_context_data(self, **kwargs):
    context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
    上下文['filter'] = self.filter
    返回上下文

现在 FilteredSingleTableView 有一个过滤器类的参数,因此您可以在 urls.py 中将其传递给其他参数:

    url(r'^$', ship.views.FilteredSingleTableView.as_view(
        模型=模型.MyModel,
        table_class=tables.MyTable,
        template_name='mytemplate.html' ,
        filter_class = filters.MyFilter,
    ) , name='myview'),

因此,您无需修改​​即可使用 FilteredSingleTableView 来过滤您的任何模型!

另请注意,我现在已将过滤器保存为实例变量并删除了f=filters.MyFilter(...)我在C中的重复代码(get_table_data 在 get_context_data 之前调用 - 如果情况并非总是如此,那么我们可以添加一个get_filter实例方法来解决问题) !

2016 年 4 月 23 日更新:根据大众的需求,我创建了一个简单的 Django 项目,该项目使用通用的 FilteredSingleTableView 类过滤书籍表。您可以在以下位置找到它:https ://github.com/spapas/django_table_filtering

更新 2016年 5 月 7 日:请注意,您应该使用Dreturn self.filter.qs中的get_table_data返回(我已经用这个更新了答案),否则视图将花费太长时间来呈现大表 - 更多信息可以在https://github.com/spapas/django_table_filtering/issues/1

于 2013-02-28T06:48:45.027 回答
4

There is an easier and DRYer way to build a generic view do this:

from django_filters.views import FilterView
from django_tables2 import SingleTableView


class FilterTableView(FilterView, SingleTableView):   
    def get_table_data(self):
        return self.object_list

So you can do this:

class MyTableView(FilterTableView):
    model = MyModel
    table_class = MyTable
    filterset_class = MyFilter
于 2015-11-13T10:38:17.570 回答
1

这是我使用 Django 2、Crispy Forms 和 Bootstrap 4 编写的应用程序的完整工作示例:

urls.py

from django.urls import path
from .views import ASTodasView


urlpatterns = [
    path("asignatura/todas", ASTodasView.as_view(), name="as-todas"),
]

视图.py

from .filters import AsignaturaListFilter
from .forms import AsignaturaFilterFormHelper
from .models import Asignatura, Calendario
from .tables import AsignaturasTable
from .utils import PagedFilteredTableView


class ASTodasView(PagedFilteredTableView):
    filter_class = AsignaturaListFilter
    model = Asignatura
    table_class = AsignaturasTable
    template_name = "asignatura/todas.html"
    formhelper_class = AsignaturaFilterFormHelper

    def get_queryset(self):
        anyo_academico = Calendario.get_anyo_academico_actual()
        return Asignatura.objects.filter(anyo_academico=anyo_academico)

过滤器.py

import django_filters
from .models import Asignatura


class AsignaturaListFilter(django_filters.FilterSet):
    class Meta:
        model = Asignatura
        fields = {
            "nombre_estudio": ["icontains"],
            "nombre_centro": ["icontains"],
            "asignatura_id": ["exact"],
            "nombre_asignatura": ["icontains"],
            "cod_grupo_asignatura": ["exact"],
        }
        order_by = ["asignatura_id"]

表格.py

from django import forms
from django.utils.translation import gettext_lazy as _

from crispy_forms.bootstrap import FormActions, InlineField
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Div, Fieldset, Layout, Submit


class AsignaturaFilterFormHelper(FormHelper):
    # See https://django-crispy-forms.readthedocs.io/en/latest/form_helper.html

    form_class = "form form-inline"
    form_id = "asignatura-search-form"
    form_method = "GET"
    form_tag = True
    html5_required = True
    layout = Layout(
        Div(
            Fieldset(
                "<span class='fa fa-search'></span> " + str(_("Buscar asignatura")),
                Div(
                    InlineField("nombre_estudio__icontains", wrapper_class="col-4"),
                    InlineField("nombre_centro__icontains", wrapper_class="col-4"),
                    InlineField("asignatura_id", wrapper_class="col-4"),
                    InlineField("nombre_asignatura__icontains", wrapper_class="col-4"),
                    InlineField("cod_grupo_asignatura", wrapper_class="col-4"),
                    css_class="row",
                ),
                css_class="col-10 border p-3",
            ),
            FormActions(
                Submit("submit", _("Filtrar")),
                css_class="col-2 text-right align-self-center",
            ),
            css_class="row",
        )
    )

表.py

import django_tables2 as tables
from django.utils.translation import gettext_lazy as _

from .models import Asignatura


class AsignaturasTable(tables.Table):
    class Meta:
        attrs = {"class": "table table-striped table-hover cabecera-azul"}
        model = Asignatura
        fields = (
            "nombre_estudio",
            "nombre_centro",
            "asignatura_id",
            "nombre_asignatura",
            "cod_grupo_asignatura",
        )
        empty_text = _(
            "No hay ninguna asignatura que satisfaga los criterios de búsqueda."
        )
        template_name = "django_tables2/bootstrap4.html"
        per_page = 20

实用程序.py

from django_tables2 import SingleTableView


class PagedFilteredTableView(SingleTableView):
    filter_class = None
    formhelper_class = None
    context_filter_name = "filter"

    def get_table_data(self):
        self.filter = self.filter_class(
            self.request.GET, queryset=super().get_table_data()
        )
        self.filter.form.helper = self.formhelper_class()
        return self.filter.qs

    def get_context_data(self, **kwargs):
        context = super(PagedFilteredTableView, self).get_context_data(**kwargs)
        context[self.context_filter_name] = self.filter
        return context

todas.html

{% extends 'base.html' %}
{% load crispy_forms_tags i18n %}
{% load render_table from django_tables2 %}

{% block title %}{% trans "Todas las asignaturas" %}{% endblock title %}

{% block content %}
<div class="container-blanco">
  <h1>{% trans "Todas las asignaturas" %}</h1>
  <hr />
  <br />

  {% crispy filter.form filter.form.helper %}
  <br />
  {% render_table table %}
</div>
{% endblock content %}

希望能帮助到你。欢迎改进。

于 2019-07-23T08:33:05.887 回答
0

如果您更喜欢django_tables2.views.SingleTableMixin与 DjangoListView或其子类(而不是SingleTableView)一起使用,我建议如下:

class FilteredListViewMixin(object):
    """ Uses django-filter to filter a ListView. """

    filter_class = None

    def get_queryset(self):
        qs = super(FilteredListViewMixin, self).get_queryset()

        self.filter = self.filter_class(self.request.GET,
                                        queryset=qs)
        return self.filter.qs

    def get_context_data(self, **kwargs):
        context = super(FilteredListViewMixin, self).get_context_data(**kwargs)
        context['filter'] = self.filter
        return context

它具有不耦合到django-tables2(DRY FTW) 的额外好处,这意味着它也可以与泛型一起使用ListViews

于 2016-10-29T13:35:17.190 回答