【问题标题】:Update Queryset of Model Choice Filter based on value of other filter根据其他过滤器的值更新模型选择过滤器的查询集
【发布时间】:2020-01-23 16:34:07
【问题描述】:

我知道我们可以在它的 init 方法中修改一个 django 过滤器,我们可以定义自定义过滤器函数来过滤查询集。

我有一个 模型选择过滤器,它从数据库中获取城市。城市包含不同的值,例如:Aachen、Achen (Kreis) 等。

self.filters["city"] = ModelMultipleChoiceFilter(
            queryset=City.objects.exclude(name__contains="Kreis").order_by("name")
        )

我有一个名为 include_kreis 的 布尔过滤器

self.filters["include_kreis"] = BooleanFilter(
            field_name="city", widget=forms.CheckboxInput, method=self.kreis_custom_filter, label="Include Kreis"
        )

如您所见,我最初排除了 Kreis 值,并且未选中该复选框。

include_kreis 过滤器的自定义函数是:

def kreis_custom_filter(self, queryset, name, value):
    if value == False:
        return queryset.exclude(city__name__contains="Kreis")
    else:
        return queryset.all()

我正在根据 Bool 过滤器的值将名称中带有 Kreis 的城市添加到查询集中。

我还想要修改模型选择过滤器 City 中的值。

类似这样的:

self.filters["city"].queryset = City.objects.all().order_by("name")

我尝试在 else 语句中的自定义过滤器函数“include_kreis”中编写上述行,但前端的下拉列表不更新值。

尝试失败:

def kreis_custom_filter(self, queryset, name, value):
    if value == False:
        return queryset.exclude(city__name__contains="Kreis")
    else:
        self.filters["city"].queryset = City.objects.all().order_by("name")
        return queryset.all()

执行此操作的一种方法可以是发送 ajax 请求并重新填充 Dropdown,但这是低效的,因为我有其他过滤器和 javascript 事件处理程序,所以 AJAX 方式是我无法采用的方式。

有没有办法更新我在自定义过滤器功能中的 ModelChoice 过滤器的查询集,还是 DJANGO 不允许?

如果可以在 init 中添加 if 语句并检查 bool 过滤器的当前值,然后:使用不同的查询集定义过滤器,这也是可以接受的。

类似于 init 中的内容:

def __init__(self, *args, result_type=None, **kwargs):
    super(Evaluation_filter, self).__init__(*args, **kwargs)
    self.filters["include_kreis"] = BooleanFilter(
        field_name="city", widget=forms.CheckboxInput, method=self.kreis_custom_filter, label="Include Kreis"
    )
    if value of bool filter == on:
      self.filters["city"] = ModelMultipleChoiceFilter(
         queryset=City.objects.all().order_by("name")
      )

    else:
      self.filters["city"] = ModelMultipleChoiceFilter(
         queryset=City.objects.exclude(name__contains="Kreis").order_by("name")
      )

【问题讨论】:

    标签: python django django-filter


    【解决方案1】:

    好的,所以我想出了解决方案:

    可以根据当前的请求在 init 方法中添加 if 语句。我注意到在 *args 中,整个请求都被发送了。

    解决办法:

    def __init__(self, *args, result_type=None, **kwargs):
        super(Evaluation_filter, self).__init__(*args, **kwargs)
        self.filters["include_kreis"] = BooleanFilter(
            field_name="city", widget=forms.CheckboxInput, method=self.kreis_custom_filter, label="Include Kreis"
        )
        #evaluate if the checkbox is checked
        if args[0] and args[0].get("include_kreis"):
            city_queryset = City.objects.all().order_by("name")
        else:
            city_queryset = City.objects.exclude(name__contains="Kreis").order_by("name")
    
        self.filters["city"] = ModelMultipleChoiceFilter(queryset=city_queryset)
    

    args[0]是字典形式的请求。

    然后我必须从中获取 include_kreis 的当前值。

    因为它是一个布尔过滤器,只有在被选中/选中时才会在请求中填充因此我使用args[0].get()

    然后根据 if 语句,我可以为城市下拉列表填充值。

    如果复选框被选中,则包括所有城市 否则排除“Kreis”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 2019-08-04
      相关资源
      最近更新 更多