Django:django-tables2分页和过滤

时间:2014-01-02 15:37:11

标签: python django django-tables2

我有一个由django-tables2生成的工作表:

my_filter = TestFilter(request.POST) 
table = TestTable(TestObj.objects.all(), order_by="-my_date")
RequestConfig(request, paginate={"per_page": 10}).configure(table)
return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})

上面的代码返回一个包含数百个对象的表,这些对象整齐地分页,每页有10个项目。当我点击表格底部的“下一步”时,分页效果很好,我可以浏览不同的页面。但是,我注意到以下行为:

  • 点击显示原始未过滤表格子集的my_filter
  • 点击已过滤表格底部的“下一步”将显示未过滤表格的第二页
  • 点击my_filter再次显示已过滤表格的第二页

我希望过滤器在导航不同页面时保持不变。我发现了一个类似的问题here。该解决方案表明需要更改html代码。但是,在我的情况下,django-tables2正在生成html。

如何使用django-tables2?

正确实现过滤分页

-Update -

我尝试过使用GET而不是POST:

if request.method == 'GET':
    my_filter = TestFilter(request.GET)
    my_choice = my_filter.data['my_choice']
    table = TestTable(TestObj.objects.filter(choice=my_choice), order_by="-my_date")
    RequestConfig(request, paginate={"per_page": 10}).configure(table)
    return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter})

我的模板:

<form action="" method="get"> {% csrf_token %}
    {{ my_filter }} <input type="submit" value="Apply Filter"/>
</form>

由于GET中不存在my_choice,导致KeyError。因此,页面甚至无法加载。

1 个答案:

答案 0 :(得分:6)

您使用的是哪个版本的django_tables2?我检查了源代码,发现django_tables2正在使用名为querystring的模板标记来创建table.html模板中的分页链接。 querystring标记使用分页参数更新当前网址。所以django_tables2支持分页+过滤开箱即用(这就是我所记得的)。

请尝试更新到最新版本的django_tables2,并确保使用默认的table.html模板来呈现您的表格。

您是也使用GET或POST提交过滤表单?请确保通过GET提交!

最后,请查看我对此问题的回答Django Tables - Column Filtering

更新:我仔细查看了您发布的代码:首先,您将帖子数据传递给过滤器:您不能使用POST,POST必须仅用于修改数据的操作。我也看到你没有过滤任何东西,而是将.all()传递给桌子!实际过滤在哪里完成?您应该将过滤后的数据传递给表格,正如我在上面的答案中所描述的那样!

更新2: 您的视图的问题是,当您第一次访问该页面时,GET字典不包含my_choice属性,因此在尝试通过{访问my_choice属性时会抛出异常{1}}运算符,因此您应该使用例如[]检查它是否确实存在,如下所示:

.get()

上面应该可行,但是你自己做了一个查询集过滤 - 几乎每个django design philosophy都违反了你的行为!

这就是为什么我告诉你读我对类似问题(Django Tables - Column Filtering)的另一个答案,其中我建议使用django-filter这是一个明确用于过滤查询集的包。请查看文档或我的答案,看看它是如何使用的(如果您有任何疑问,我很乐意提供帮助)。

此外,您的代码还存在许多其他小问题:

  • 您无需检查my_filter = TestFilter(request.GET) my_choice = my_filter.data.get('my_choice') # This won't throw an exception if my_choice: # If my_choice existed on the GET dictionary this will return non-null value table = TestTable(TestObj.objects.filter(choice=my_choice), order_by="-my_date") else: table = TestTable(TestObj.objects.all(), order_by="-my_date") RequestConfig(request, paginate={"per_page": 10}).configure(table) return render(request, 'test_app/index.html', {'table': table, 'my_filter': my_filter}) 是否为request.method - 它始终为GET,因为您不会GET < / p>

  • 您不应该在模板中加入POST - {{ csrf_token }}只需要{。}}。

  • POST类实际上是TestFilter,这就是为什么我建议将其命名为Form或类似的东西 - 如果你使用了django-filter那么你就创建了TestFilterForm类,其名称为FilterSet。正确命名类是非常重要的,当我第一次看到你的代码时,我认为TestFilter TestFilter而不是FilterSet