django-filters使用ModelChoiceFilter来获取ForeignKey的值

时间:2018-06-25 16:09:18

标签: django django-models django-forms foreign-keys

我正在尝试使用ModelChoiceFilter来过滤基于作者的字母数据库。作者是一个外键,我似乎无法显示外键的“名称”值。

这是我所拥有的:

models.py(仅限相关位)

class Person(models.Model):
    name = models.CharField(max_length=250, verbose_name='Full Name')
    ...

    def __str__(self):
        return self.name

class Letter(models.Model):
    author = models.ForeignKey(Person, related_name='author', on_delete=models.PROTECT, verbose_name='Letter Author')
    recipient = models.ForeignKey(Person, related_name='recipient', on_delete=models.PROTECT, verbose_name='Recipient')
    ...
    title = models.CharField(max_length=250, verbose_name='Title of Letter')

    def __str__(self):
        return self.title

letter_filters.py

class LetterFilter(django_filters.FilterSet):
    ...
    author = django_filters.ModelChoiceFilter(queryset=Letter.objects.order_by('author__name'))

    class Meta:
        model = Letter
        fields = ['author', 'recipient']

我可以看到这种作品。这确实是对它的限制和正确排序,但是不是在选择框中显示作者姓名,而是在信件中显示“标题”(但我可以从标题中以正确的顺序看出来)。

我认为应该起作用的是这个

fields = ['author__name', 'recipient']

但这仍然继续列出Letter中的“标题”,而不是Person中的“名称”。

我知道它有我需要的,因为如果我这样做:

 author = django_filters.ModelChoiceFilter(queryset=Letter.objects.order_by('author__name').values('author__name'))

我完全得到了我想要的!但是,它以{'author__name':'Jane Doe'}的形式出现,字段为author或author_name。我似乎无法获得正确的语法。

最后,我知道我可以做到:

author = django_filters.ModelChoiceFilter(queryset=Person.objects.order_by('name'))

返回正确排序的所有人员。但是,数据库中的人员不仅仅是作者。这与只允许使用默认字段['author'...,而不在类中设置author =(尽管无序)一样。

1 个答案:

答案 0 :(得分:2)

您指定的查询集处理Letter,因此,在这种情况下,Letter被添加到ModelChoiceFiler中,这根本不理想。

不过,您可以生成Person的列表,这些列表至少写了一个字母,例如:

django_filters.ModelChoiceFilter(
    queryset=Person.objects.filter(letter_set__isnull=False).order_by('name').distinct()
)

因此,这里我们过滤letter_set不为空的事实,由于这将导致JOIN,其中Person可能出现多次,因此我们向其中添加.distinct()

我发现这种建模非常奇怪(在您的三个示例中)。这基本上意味着您只能分配已经写入Person的{​​{1}}。如果从未写过Letter的人想写Letter怎么办?

通常情况下,如果角色不同,则可以添加Letter

BooleanField

然后,我们可以过滤class Person(models.Model): name = models.CharField(max_length=250, verbose_name='Full Name') is_author = models.BooleanField(verbose_name='Is the person an author') # ...Person上的内容:

Author