【问题标题】:Django Tables - Column FilteringDjango 表 - 列过滤
【发布时间】:2012-11-28 18:14:15
【问题描述】:

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

【问题讨论】:

    标签: python django django-tables2


    【解决方案1】:

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

    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:这可能是最 DRY 的方式 :) 下面是如何做到的:

    首先定义一个过滤器:

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

    (或者你可以在 Meta 中添加模型过滤器(model = 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= 表格.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= 过滤器.MyFilter, ) , name='myview'),

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

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

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

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

    【讨论】:

      【解决方案2】:

      有一种更简单、更干的方法来构建通用视图:

      from django_filters.views import FilterView
      from django_tables2 import SingleTableView
      
      
      class FilterTableView(FilterView, SingleTableView):   
          def get_table_data(self):
              return self.object_list
      

      所以你可以这样做:

      class MyTableView(FilterTableView):
          model = MyModel
          table_class = MyTable
          filterset_class = MyFilter
      

      【讨论】:

      • 和? thish 是来自官方网站的示例。制作网址并查看
      【解决方案3】:

      这是一个完整的工作示例,来自我使用 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"),
      ]
      

      views.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)
      

      filters.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"]
      

      forms.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",
              )
          )
      

      tables.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
      

      utils.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 %}
      

      希望对您有所帮助。欢迎改进。

      【讨论】:

        【解决方案4】:

        如果您更喜欢将 django_tables2.views.SingleTableMixin 与 Django 的 ListView 或其子类(而不是 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-03-04
          • 1970-01-01
          • 2011-01-10
          • 2017-03-27
          • 2020-08-02
          • 2016-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多