gpt4 book ai didi

django - Django Rest Framework 序列化程序中的聚合(和其他带注释的)字段

转载 作者:行者123 更新时间:2023-11-28 19:35:00 25 4
gpt4 key购买 nike

我正在尝试找出向 DRF(模型)序列化程序添加注释字段(例如任何聚合(计算)字段)的最佳方法。我的用例只是一个端点返回未存储在数据库中但从数据库计算的字段的情况。

让我们看下面的例子:

模型.py

class IceCreamCompany(models.Model):
name = models.CharField(primary_key = True, max_length = 255)

class IceCreamTruck(models.Model):
company = models.ForeignKey('IceCreamCompany', related_name='trucks')
capacity = models.IntegerField()

序列化器.py

class IceCreamCompanySerializer(serializers.ModelSerializer):
class Meta:
model = IceCreamCompany

所需的 JSON 输出:

[

{
"name": "Pete's Ice Cream",
"total_trucks": 20,
"total_capacity": 4000
},
...
]

我有几个可行的解决方案,但每个都有一些问题。

选项 1:向模型添加 getter 并使用 SerializerMethodFields

模型.py

class IceCreamCompany(models.Model):
name = models.CharField(primary_key=True, max_length=255)

def get_total_trucks(self):
return self.trucks.count()

def get_total_capacity(self):
return self.trucks.aggregate(Sum('capacity'))['capacity__sum']

序列化器.py

class IceCreamCompanySerializer(serializers.ModelSerializer):

def get_total_trucks(self, obj):
return obj.get_total_trucks

def get_total_capacity(self, obj):
return obj.get_total_capacity

total_trucks = SerializerMethodField()
total_capacity = SerializerMethodField()

class Meta:
model = IceCreamCompany
fields = ('name', 'total_trucks', 'total_capacity')

上面的代码或许可以稍微重构一下,但它不会改变这个选项将执行 2 个额外的 SQL 查询每个 IceCreamCompany 的事实,这不是很有效。

选项 2:在 ViewSet.get_queryset 中注释

最初描述的 models.py。

View .py

class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.all()
serializer_class = IceCreamCompanySerializer

def get_queryset(self):
return IceCreamCompany.objects.annotate(
total_trucks = Count('trucks'),
total_capacity = Sum('trucks__capacity')
)

这将在单个 SQL 查询中获取聚合字段,但我不确定如何将它们添加到序列化程序,因为 DRF 并不知道我已经在 QuerySet 中注释了这些字段。如果我将 total_trucks 和 total_capacity 添加到序列化程序,它会抛出有关模型中不存在这些字段的错误。

通过使用 View,选项 2 可以在没有序列化器的情况下工作。但是如果模型包含很多字段,并且只有一些字段需要在 JSON 中,那么在没有序列化程序的情况下构建端点将是一个有点丑陋的 hack。

最佳答案

可能的解决方案:

View .py

class IceCreamCompanyViewSet(viewsets.ModelViewSet):
queryset = IceCreamCompany.objects.all()
serializer_class = IceCreamCompanySerializer

def get_queryset(self):
return IceCreamCompany.objects.annotate(
total_trucks=Count('trucks'),
total_capacity=Sum('trucks__capacity')
)

序列化器.py

class IceCreamCompanySerializer(serializers.ModelSerializer):
total_trucks = serializers.IntegerField()
total_capacity = serializers.IntegerField()

class Meta:
model = IceCreamCompany
fields = ('name', 'total_trucks', 'total_capacity')

通过使用 Serializer fields我有一个小例子可以工作。这些字段必须声明为序列化程序的类属性,这样 DRF 就不会抛出关于它们在 IceCreamCompany 模型中不存在的错误。

关于django - Django Rest Framework 序列化程序中的聚合(和其他带注释的)字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31920853/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com