如何从反向相关模型序列化字段 - Django rest framework

时间:2015-05-01 10:45:31

标签: django-rest-framework

我有一个api,它通过带有额外订单字段的manytomany模型检索与项目相关的所有项目。我现在正在尝试使用订单值序列化项目。

一种解决方案是序列化直通模型,但结果如下:

{
    "order": 1,
    "item": {
        "id": 3031,
        "name": "Miami"
    }
},

我想序列化该项目并获得如下输出:

{
    "order": 1,
    "id": 3031,
    "name": "Miami"
}

我无法将订单作为属性添加到商品模型中,因为它是一个很多领域。或者我想我可以,但必须采取列表的第一个对象,这不是我认为非常干净的解决方案,可能会添加一个单独的数据库调用。

所有项目都是这样获取的:

ProjectItem.objects.filter(project_id=self.kwargs['project_pk']).select_related('item')

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

如果您有直通模型,那么您应该对其进行序列化并使用source额外参数来“展平”表示。

例如,对于name,它将是

name = serializers.CharField(source='item.name')

您可能必须编写序列化程序创建/更新方法,以使其适用于可写。

答案 1 :(得分:0)

如果由于某些原因不希望像@Linovia建议那样浏览直通模型,那么你可以预取直通模型并使用带有覆盖的to_representation的RelatedField。

这就是我所做的:

from django.db.models import Prefetch

Item.objects.filter(projectitem_set__project_id=self.kwargs['project_pk'])
    .prefetch_related(
        Prefetch('projectitem_set', queryset=ProjectItem.objects.filter(project_id=self.kwargs['project_pk']), to_attr='order'))

然后将其添加到ItemSerializer中(不要添加many = True):

order = ProjectItemSerializer(read_only=True)

并覆盖ProjectItemSerializer中的to_representation:

class ProjectItemSerializer(serializers.RelatedField):
    def to_representation(self, value):
        return value[0].order

value [0]获取预取值的第一个对象