【发布时间】:2016-01-03 01:36:30
【问题描述】:
我正在尝试查看 Django REST Framework 序列化程序中的嵌套注释(聚合/计算)字段。这将允许更干净地处理带注释的字段。这篇文章与Aggregate (and other annotated) fields in Django Rest Framework serializers 类似,但是我想要一种类似的嵌套技术。在方法下方可以看到如何在没有嵌套的情况下工作,以及如何在嵌套情况下不工作。
我知道这可以手动实现(使用 Django 视图)或通过使用使我不感兴趣的数据库重载的方法来实现。但也许有一个高性能且优雅的解决方案来解决这个问题。
以下作品(未嵌套)
模型
class IceCreamCompany(models.Model):
name = models.CharField(max_length=255)
class IceCreamTruck(models.Model):
company = models.ForeignKey('IceCreamCompany', related_name='trucks')
capacity = models.IntegerField()
class IceCreamTruckDriver(models.Model):
name = models.CharField(max_length=255)
first_name = models.CharField(max_length=255)
truck = models.ForeignKey('IceCreamTruck', related_name='drivers')
序列化器
class IceCreamTruckDriverSerializer(serializers.ModelSerializer):
class Meta:
model = IceCreamTruckDriver
fields = ('name', 'first_name')
class IceCreamTruckSerializer(serializers.ModelSerializer):
drivers = IceCreamTruckDriverSerializer(many=True, read_only=True)
class Meta:
model = IceCreamTruck
fields = ('capacity', 'drivers')
class IceCreamCompanySerializer(serializers.ModelSerializer):
trucks = IceCreamTruckSerializer(many=True, read_only=True)
amount_of_trucks = serializers.IntegerField()
class Meta:
model = IceCreamCompany
fields = ('name', 'trucks', 'amount_of_trucks')
视图集
class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.prefetch_related('trucks', 'trucks__drivers')\
.annotate(amount_of_trucks=Count('trucks'))\
.all()
serializer_class = IceCreamCompanySerializer
结果
"results": [
{
"name": "Pete Ice Cream",
"trucks": [
{
"capacity": 35,
"drivers": [
{
"name": "Damian",
"first_name": "Ashley"
},
{
"name": "Wilfrid",
"first_name": "Lesley"
}
]
},
{
"capacity": 30,
"drivers": [
{
"name": "Stevens",
"first_name": "Joseph"
}
]
},
{
"capacity": 30,
"drivers": []
}
],
"amount_of_trucks": 3
}
]
以下不起作用(嵌套)
同款
序列化器
class IceCreamTruckDriverSerializer(serializers.ModelSerializer):
class Meta:
model = IceCreamTruckDriver
fields = ('name', 'first_name')
class IceCreamTruckSerializer(serializers.ModelSerializer):
drivers = IceCreamTruckDriverSerializer(many=True, read_only=True)
amount_of_drivers = serializers.IntegerField()
class Meta:
model = IceCreamTruck
fields = ('capacity', 'drivers', 'amount_of_drivers')
class IceCreamCompanySerializer(serializers.ModelSerializer):
trucks = IceCreamTruckSerializer(many=True, read_only=True)
class Meta:
model = IceCreamCompany
fields = ('name', 'trucks')
视图集
class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.prefetch_related('trucks', 'trucks__drivers')\
.annotate(trucks__amount_of_drivers=Count('trucks__drivers'))\
.all()
serializer_class = IceCreamCompanySerializer
结果
AttributeError at /ice/
Got AttributeError when attempting to get a value for field `amount_of_drivers` on serializer `IceCreamTruckSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `IceCreamTruck` instance.
Original exception text was: 'IceCreamTruck' object has no attribute 'amount_of_drivers'.
【问题讨论】:
-
您不应该将字段命名为 amount_of_drivers 而不是 trucks__amount_of_drivers 吗?
-
如果我在查询集中的注释函数中使用 amount_of_drivers,它会尝试在 IceCreamCompanySerializer 中查找 amount_of_drivers 字段,该字段不是嵌套的注释字段。我希望它在 IceCreamTruckSerializer 中成为可能。
-
不,先生,我只是建议重命名注释: .annotate(amount_of_drivers=Count('trucks__drivers'));错误命名了这个问题,在查询集中没有找到带注释的列的名称这一事实。注释列的名称只是一个名称,不会为您遍历关系。
-
您好,您最终能否在不使用
SerializerMethodField的情况下实现这一目标? -
@NicholasColes 是的,我仍然使用自定义视图,这不是最佳的。但是,您可以尝试自定义管理器,如 Campi 在另一个答案中所述。对于我的用例,这种方法会使其过于复杂。我也没有检查查询量。
标签: django django-rest-framework