【问题标题】:Django: django-tables2 pagination and filteringDjango:django-tables2 分页和过滤
【发布时间】:2014-01-02 15:37:11
【问题描述】:

我有一个由 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 正确实现分页过滤?

-更新-

我尝试过使用 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。结果页面甚至没有加载。

【问题讨论】:

    标签: python django django-tables2


    【解决方案1】:

    您使用的是哪个版本的 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 design philosophy

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

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

    • 您无需检查request.method 是否为GET - 它始终为GET,因为您不会执行任何POSTs

    • 您不应该在模板中包含{{ csrf_token }} - 只有POST 需要它。

    • 1234563会被命名为TestFilter。正确命名类非常重要,当我第一次看到您的代码时,我认为 TestFilter FilterSet 而不是 Form

    【讨论】:

    • 我正在使用最新的 django-tables2 (0.14.0)。我已经用 GET 和 POST 进行了测试。我最终暂时禁用了分页:(
    • 我已经用我的 GET/POST 测试的详细信息更新了这个问题。你能指出我做错了什么吗?
    • 请查看更新 2 以解决您的问题和一些一般性建议!
    • 这为我解决了问题。感谢您非常彻底的回复。非常感谢:)
    • 当然。我还是个正在学习的婴儿,总是会消化学习者的建议。
    猜你喜欢
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2016-06-11
    • 2015-08-12
    • 2019-08-17
    相关资源
    最近更新 更多