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.0
,name
参数更改为 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')),
...
}),
...
}
我有两张桌子。
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.0
,name
参数更改为 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')),
...
}),
...
}