我有两个桌子。
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?
答案 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
由于 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')),
...
}),
...
}