6

我有一个由 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哪个显示原始未过滤表的子集
  • 点击过滤后表格底部的“下一步”将显示未过滤表格的第 2 页
  • 再次点击my_filter显示过滤表的第 2 页

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

如何使用 django-tables2 正确实现分页过滤?

-更新-

我尝试使用 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>

my_choice由于GET 中不存在,这会导致 KeyError 。结果页面甚至没有加载。

4

1 回答 1

6

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

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

您还使用 GET 或 POST 提交您的过滤器表单吗?请确保使用 GET 提交!

最后,请看一下我对这个问题的回答Django Tables - Column Filtering

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

更新2: 您的观点的问题是,当您第一次访问该页面时,GET字典不包含该属性,因此在尝试通过运算符my_choice访问该属性时会引发异常,因此您应该检查它是否确实存在使用例如,像这样:my_choice[].get()

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})

以上应该可以工作,但是通过自己进行查询集过滤 -你几乎违反了每一个django 设计理念

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

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

  • 你不需要检查是否request.methodGET- 它总是GET因为你不会做任何POSTs

  • 您不应该将其包含{{ csrf_token }}到您的模板中 - 它仅适用于POST.

  • 这个TestFilter类实际上是一个Form这就是为什么我建议命名它 TestFilterForm或类似的东西——如果你使用过 django-filter 那么你会创建一个FilterSet名为TestFilter. 类的正确命名非常重要,当我第一次看到你的代码时,我认为TestFilteraFilterSet而不是 a Form

于 2014-01-03T17:37:57.117 回答