【问题标题】:Django Admin custom list_filter is not called未调用 Django Admin 自定义 list_filter
【发布时间】:2018-06-25 03:06:43
【问题描述】:

我使用https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter 上的教程为我的 ModelAdmin 编写了一个自定义列表过滤器。 当从项目中取出到测试环境中并直接输入过滤器值时,它可以正常工作。然而,在实际项目中,它会显示过滤器选项,但在选择过滤器时不会更改结果。 奇怪的是,参数设置为“balance”,查找列表定义了“positive”、“negative”和“settled”;但相应的 URL 查询字符串只会显示?e=1。即使我直接输入查询字符串(例如?balance=positive),我也会被重定向到?e=1 并查看所有对象。 代码如下:

class AccountBalanceFilter(admin.SimpleListFilter):
    title           = "Kontostand"
    parameter_name  = "balance"
    def lookups(self, request, model_admin):
        return (("positive",  "Positiv"),
                ("negative",  "Negativ"),
                ("settled",   "Ausgeglichen"),)
    def queryset(self, request, queryset):
        filter = self.value()
        if filter is None:
            return queryset
        elif filter == "positive":
            filtered_set = {account for account in queryset if account.get_current_balance() > 0}
        elif filter == "negative":
            filtered_set = {account for account in queryset if account.get_current_balance() < 0}
        elif filter == "settled":
            filtered_set = {account for account in queryset if account.get_current_balance() == 0}
        else:
            raise ValueError(f"The account balance filter only accepts filter values of 'positive', 'negative', or 'settled', but was given '{self.value()}'!")
        return filtered_set

有什么建议吗?

【问题讨论】:

  • 你是如何在 ModelAdmin 中引用这个过滤器的?
  • 是的,我有,像这样:class AccountAdmin(admin.ModelAdmin): [...] list_filter = (AccountBalanceFilter,)。它甚至显示在页面上,我可以单击不同的选项,页面重新加载,但没有效果。如果我直接传入要过滤的值,它就可以正常工作。所以我怀疑某处管理员的 URL 构造存在问题。

标签: django django-admin


【解决方案1】:

好的,所以经过一些调试后,我发现?e=1 查询字符串是管理员告诉我们存在格式错误的数据的方式......我原本希望在这种情况下看到异常。 问题实际上很简单:管理员需要一个 Queryset 对象,并且不理解常规(Python)集合。由于不可能在 Django 的数据库 API 之外构建 Queryset,因此解决方案是从我想要的对象中提取 id 并返回由该 id 列表过滤的 Queryset,如下所示:

[...]
elif filter == "positive":
            filtered_ids = [account.id for account in queryset if account.get_current_balance() > 0]
[...]
return Account.objects.filter(id__in=filtered_ids)

这样就可以了。现在我也可以按照here 的说明订购了。

【讨论】:

    猜你喜欢
    • 2011-10-17
    • 1970-01-01
    • 2016-06-02
    • 2012-08-19
    • 2019-07-11
    • 2012-03-30
    • 2012-04-06
    • 2011-01-16
    • 2011-10-08
    相关资源
    最近更新 更多