Django-filter 按相关字段过滤

Django-filter filter by related fields

我有两张桌子。

class Writer(models.Model)
    name = model.CharField()
    ...

class Article(models.Model)
    name = model.CharField()
    writer = model.ForeignKey('Writer', related_name="relationship") 
    ...

我想构建一些 API 端点来获取作者列表,但这应该可以按文章 ID 进行过滤。 我正在使用 django 过滤器。所以:

class WriterViewSet(viewsets.ReadOnlyModelViewSet):
   filter_backend = [filters.djangoFilterBackend],
   filter_class = WriterFilter


class WriteFilter(django_filters.rest_framework.FilterSet):
....

所以我担心的是,如何定义 WriteFilter 以按文章过滤 Writer?

你可以这样试试。我的 class 使用新参数自定义过滤器。您的 api 必须有额外的参数。在这种情况下是 ?article_name='example'

class WriteFilter(django_filters.rest_framework.FilterSet):
    class Meta:
        model = WriterFilter
        fields = ['article_name']
    article_name = ArticleFilter(name="article_name")

class ArticleFilter(django_filters.Filter):
    def filter(self, qs, value):
        return qs.article_set.filter(name=value)

如果你 运行 queryset,它会得到文章名称为 'example' 的所有 Writer。

支持这个帮助

class WriteFilter(django_filters.rest_framework.FilterSet):
    article = django_filters.CharFilter(name='relationship__name', lookup_expr='contains')

    class Meta:
        model = WriterFilter
        fields = ['article']


你的url会是这样,
/api/wtiter/list/?article=somearticlename


更新-1

由于 django-filter 2.0name 参数更改为 field_name.

因此过滤器 class 将是,

class WriteFilter(django_filters.rest_framework.FilterSet):
    article = django_filters.CharFilter(<b>field_name</b>='relationship__name', lookup_expr='contains')

    class Meta:
        model = WriterFilter
        fields = ['article']

JPG 答案是正确的,但如果你有很多领域和关系,这将是一项繁琐的工作。但是你实际上可以在 field meta:

中声明关系
class ArticleFilter(django_filters.rest_framework.FilterSet):
    class Meta:
        model = Article
        fields = ['article', 'writer__name']

或使用查找表达式:

class ArticleFilter(django_filters.rest_framework.FilterSet):
    class Meta:
        model = Article
        fields = {
            'article': ('exact', ),
            'relationship__name': ('exact', 'contains')
            }

还有更多优化:

def prefix_dict_keys(prefix: str, d: dict):
    return {prefix + k: v for k, v in d.items()}

class ArticleFilter(django_filters.rest_framework.FilterSet):
    class Meta:
        model = Article
        fields = {
            'article': ('exact', ),
            ...
            **prefix_dict_keys('writer__'
                {
                   'name': ('exact', 'contains')),
                   ...
                }),
            ...
            }