Django-filter: 按外键模型的属性过滤

创建于 2019-01-09  ·  4评论  ·  资料来源: carltongibson/django-filter

你好呀!

我正在处理工作中的一个问题,想知道解决它的最惯用的方法是什么。 我们有多个ModelMultipleChoiceFilter过滤器字段用于模型的外键。 我试图弄清楚如何在使用CheckboxSelectMultiple小部件时按外键上的唯一属性进行过滤,而不在 URL 中公开主键。

这是一个(或多或少)示例,显示了我现在如何设置它。

# app/models.py
from django.db import models

class Foo(models.Model):
    prop = models.CharField(max_length=55, unique=True)

    def __str__(self):
        return self.name


class Bar(models.Model):
    foo = models.ForeignKey(Foo, related_name="bars")
# app/filters.py
import django_filters
from app.models import Bar, Foo

class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

这在视图中完全正常。 过滤器使用正确的小部件正常工作和过滤。 但是,网址中有主键,因此在此示例中/?foo=1 ,而我希望它读取/?foo=<prop value> ,以防止暴露我的 pk 并使网址更具可读性。

我尝试修改这样的字段,因为在 Django 的其他地方它往往可以工作:

# app/filters.py
...snip...
    class Meta:
        model = bar
        fields = ['foo__prop']

这使 url 根据需要响应/?foo=<prop value> ,但现在它不使用CheckboxSelectMultiple作为表单。 我也尝试将属性设置为foo__prop ,但表单渲染仍然不正确。

我有一种感觉,考虑到它几乎可以工作,我正在尝试做的事情得到了支持,但我似乎无法弄清楚如何获得它。 如果这超出了当前支持的范围,我可以编写自己的表单来处理这个问题。 非常感谢您提供的任何帮助和出色的项目!

最有用的评论

您好,感谢您花时间回复!

你让我走上了正轨! 我昨天有机会实现这一点,并且使用field_name参数起作用了!

对于将来可能会阅读此问题的任何人,以下是代码的大致方式:

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

您可以在文档@carltongibson提到的线程中找到对此的引用。 具体来说,请参阅 ModelMultipleChoice 过滤器部分。

无论如何,非常感谢您抽出时间来帮助我!

所有4条评论

嗨。 不错的问题。 严格来说是一个用法问题,但说得好,读起来很愉快。

您是否查看了过滤器的 field_name 参数?
https://django-filter.readthedocs.io/en/master/ref/filters.html

这将允许您使用 foo_prop 作为 foo 过滤器的目标。

我想那只是工作......也许你需要在小部件上设置选择等(但应该处理......)

您好,感谢您花时间回复!

你让我走上了正轨! 我昨天有机会实现这一点,并且使用field_name参数起作用了!

对于将来可能会阅读此问题的任何人,以下是代码的大致方式:

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

您可以在文档@carltongibson提到的线程中找到对此的引用。 具体来说,请参阅 ModelMultipleChoice 过滤器部分。

无论如何,非常感谢您抽出时间来帮助我!

极好的。 很高兴你解决了它。 做得好!

很好 ! 谢谢 !

此页面是否有帮助?
0 / 5 - 0 等级