有没有办法从 ModelViewSet 中的 RelatedManager 中过滤掉项目?
Is there a way to filter out items from RelatedManager in a ModelViewSet?
我正在使用 DRF 进行简单的 API,我想知道是否有办法实现此行为:
- 我有两个类似于以下的模型:
class Table(models.Model):
name = models.CharField(max_length=100)
...
class Column(models.Model):
original_name = models.CharField(max_length=100)
name = models.CharField(max_length=100, blank=True, null=True)
...
table = models.ForeignKey(Table, on_delete=models.CASCADE, related_name="columns")
- 它们的序列化器如下:
class ColumnSerializer(serializers.HyperlinkedModelSerializer):
table = serializers.HyperlinkedRelatedField(
read_only=True, view_name="table-detail"
)
class Meta:
model = Column
fields = ["url", "name", "table"]
class TableSerializer(serializers.HyperlinkedModelSerializer):
dataset = serializers.HyperlinkedRelatedField(
read_only=True, view_name="dataset-detail"
)
tags = serializers.SlugRelatedField(
many=True, slug_field="name", queryset=Tag.objects.all()
)
columns = ColumnSerializer(many=True, read_only=True)
class Meta:
model = Table
fields = [
"url",
"name",
...
"columns",
]
- 这个returns我的输出类似于
{
...
"results": [
{
"url": "http://0.0.0.0:8001/api/tables/1/",
"name": "some-name",
"columns": [
{
"url": "http://0.0.0.0:8001/api/columns/1/",
"name": "id",
"table": "http://0.0.0.0:8001/api/tables/1/"
},
...
}
完全没问题。但是 我真正想做的是 ,如果 Column
有 name=None
,它会从每个 API ViewSet 中过滤掉。我已经通过 queryset = queryset.filter(name__isnull=False)
在 ColumnViewSet
上做到了,但我不能对 TableViewSet
或其他可能显示 Column
列表的人做到这一点。
我试过修改 ColumnSerializer
,但我能从中得到的最好结果是在 Column
列表中显示 null
s。
我想知道是否有隐藏这些的方法。
编辑 1:添加我的视图集
class TableViewSet(viewsets.ModelViewSet):
serializer_class = TableSerializer
def get_queryset(self):
queryset = Table.objects.all().order_by("name")
# some query_params filtering
return queryset
class ColumnViewSet(viewsets.ModelViewSet):
serializer_class = ColumnSerializer
def get_queryset(self):
queryset = Column.objects.all().order_by("id")
queryset = queryset.filter(name__isnull=False)
# some query_params filtering
return queryset
您可以使用 Prefetch
object [Django-doc] 来过滤相关对象集合,因此:
from django.db.models import <strong>Prefetch</strong>
class TableViewSet(viewsets.ModelViewSet):
serializer_class = TableSerializer
def get_queryset(self):
queryset = Table.objects.prefetch_related(
Prefetch('columns', <strong>Column.objects.filter(name__isnull=False)</strong>)
).order_by('name')
# some query_params filtering
return queryset
我正在使用 DRF 进行简单的 API,我想知道是否有办法实现此行为:
- 我有两个类似于以下的模型:
class Table(models.Model):
name = models.CharField(max_length=100)
...
class Column(models.Model):
original_name = models.CharField(max_length=100)
name = models.CharField(max_length=100, blank=True, null=True)
...
table = models.ForeignKey(Table, on_delete=models.CASCADE, related_name="columns")
- 它们的序列化器如下:
class ColumnSerializer(serializers.HyperlinkedModelSerializer):
table = serializers.HyperlinkedRelatedField(
read_only=True, view_name="table-detail"
)
class Meta:
model = Column
fields = ["url", "name", "table"]
class TableSerializer(serializers.HyperlinkedModelSerializer):
dataset = serializers.HyperlinkedRelatedField(
read_only=True, view_name="dataset-detail"
)
tags = serializers.SlugRelatedField(
many=True, slug_field="name", queryset=Tag.objects.all()
)
columns = ColumnSerializer(many=True, read_only=True)
class Meta:
model = Table
fields = [
"url",
"name",
...
"columns",
]
- 这个returns我的输出类似于
{
...
"results": [
{
"url": "http://0.0.0.0:8001/api/tables/1/",
"name": "some-name",
"columns": [
{
"url": "http://0.0.0.0:8001/api/columns/1/",
"name": "id",
"table": "http://0.0.0.0:8001/api/tables/1/"
},
...
}
完全没问题。但是 我真正想做的是 ,如果 Column
有 name=None
,它会从每个 API ViewSet 中过滤掉。我已经通过 queryset = queryset.filter(name__isnull=False)
在 ColumnViewSet
上做到了,但我不能对 TableViewSet
或其他可能显示 Column
列表的人做到这一点。
我试过修改 ColumnSerializer
,但我能从中得到的最好结果是在 Column
列表中显示 null
s。
我想知道是否有隐藏这些的方法。
编辑 1:添加我的视图集
class TableViewSet(viewsets.ModelViewSet):
serializer_class = TableSerializer
def get_queryset(self):
queryset = Table.objects.all().order_by("name")
# some query_params filtering
return queryset
class ColumnViewSet(viewsets.ModelViewSet):
serializer_class = ColumnSerializer
def get_queryset(self):
queryset = Column.objects.all().order_by("id")
queryset = queryset.filter(name__isnull=False)
# some query_params filtering
return queryset
您可以使用 Prefetch
object [Django-doc] 来过滤相关对象集合,因此:
from django.db.models import <strong>Prefetch</strong>
class TableViewSet(viewsets.ModelViewSet):
serializer_class = TableSerializer
def get_queryset(self):
queryset = Table.objects.prefetch_related(
Prefetch('columns', <strong>Column.objects.filter(name__isnull=False)</strong>)
).order_by('name')
# some query_params filtering
return queryset