Django过滤器按相关字段过滤

时间:2018-07-22 18:27:11

标签: django django-models django-rest-framework django-filter

我有两个桌子。

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

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

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

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


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

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

3 个答案:

答案 0 :(得分:3)

您可以尝试这样。我的班级用新的参数定制了过滤器。您的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。

获取帮助

答案 1 :(得分:3)

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

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


您的网址就是这样,
/api/wtiter/list/?article=somearticlename


UPDATE-1

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

因此,过滤器类将是

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

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

答案 2 :(得分:2)

JPG的答案是正确的,但是如果您有很多领域和关系,那将是一件繁琐的工作。但是您实际上可以在field元中声明关系:

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')),
                   ...
                }),
            ...
            }