我有以下型号:
class Section(models.Model):
name = models.CharField(max_length=255)
class Dataset(models.Model):
name = models.CharField(max_length=255)
sections = models.ManyToManyField(Section)
class File(models.Model):
dataset = models.ForeignKey(Dataset)
section = models.ForeignKey(Section, related_name='files')
key = models.CharField(max_length=255)
串行器:
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = ('id', 'key')
class SectionSerializer(serializers.ModelSerializer):
files = FileSerializer(many=True)
class Meta:
model = Section
fields = ('name', 'files')
class DatasetSerializer(serializers.ModelSerializer):
sections = SectionSerializer(many=True)
class Meta:
model = Dataset
fields = ('id', 'name', 'sections')
and viewset:
class DatasetsViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = DatasetSerializer
queryset = Dataset.objects.prefetch_related(
'sections', 'sections__metric', 'sections__feature', 'sections__files')
我正在尝试使用其部分列表加载数据集(/api/datasets
端点),并为每个部分加载与之相关的文件列表:
[
{
"id": 1,
"name": "Q4 2015",
"sections": [
{
"id": 1,
"name": "Overall Scores"
"files": [
{
"id": 1,
"key": "this/is/a/path"
}
]
}
]
}
]
棘手的部分是,父数据集应该过滤给定部分的文件列表。现在,这些部分包含所有文件,无论其数据集如何。最好的方法是什么?
谢谢!
答案 0 :(得分:1)
好的,所以我找到了一个解决方案,我不知道这是否是最好的方法,但这对我有用:我修改了序列化程序,将父对象传递给了孩子们。
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = ('id', 'key')
class SectionSerializer(serializers.ModelSerializer):
files = serializers.SerializerMethodField()
def get_files(self, obj):
dataset_id = self.context.get('dataset_id')
if dataset_id:
return FileSerializer(many=True).to_representation(
[f for f in obj.files.all() if f.dataset_id == dataset_id]
# Using
# obj.files.filter(dataset_id=dataset_id)
# would hit the database for every section making the
# prefetching useless
)
return FileSerializer(many=True).to_representation(obj.files.all())
class Meta:
model = Section
fields = ('name', 'files')
class DatasetSerializer(serializers.ModelSerializer):
sections = serializers.SerializerMethodField()
def get_sections(self, obj):
context = self.context
context.update({'dataset_id': obj.id})
return SectionSerializer(many=True, context=context).to_representation(
obj.sections
)
class Meta:
model = Dataset
fields = ('id', 'name', 'sections')
答案 1 :(得分:0)
执行此操作的一种方法是使用query param
。
您可以覆盖get_queryset
以在ViewSet
中查找此查询参数,如下所示:
def get_queryset(self):
qs = super(DatasetsViewSet, self).get_queryset()
dataset = self.request.query_params.pop('dataset', None)
if dataset:
qs = qs.filter(dataset=dataset)
return qs
带有查询参数的示例网址(假设您的API基本网址为/api/files/
)将为:
'/api/files/?dataset=1'