如何序列化 Django 模型中的多个对象并在每个对象的输出 JSON 中添加动态计算的数据?
How to serialize multiples objects from a Django model and add dynamically computed data in outputed JSON for each object?
我正在将 Laravel PHP 代码移植到 Python Django/Django Rest Framework。
我的端点将输出 JSON.
我需要输出很多对象,但我需要为每个对象添加额外的计算值。
我怎样才能做到这一点?
比如我的模型是:
from django.db import models
from rest_framework.serializers import ModelSerializer
class MyObject(models.Model):
name = models.CharField(max_length=255)
score = models.IntegerField()
class MyObjectSerializer(ModelSerializer):
class Meta:
model = MyObject
fields = ( 'name', 'score' )
我使用 MyObject.objects.all()
(或过滤器)检索了一个查询集。
对于我的查询集中的每个 MyObject,我计算一个额外的值,称为 'stats',我想在我的 JSON 输出中输出它。
例如,如果我有 2 个对象 MyObject(name='foo',score='1') 和 MyObject(name='bar',score='2'),我将计算每个对象的统计值。
我的 JSON 输出应该是这样的:
{
{
'name': 'foo',
'score': 1,
'stats': 1.2
},
{
'name': 'bar',
'score': 2,
'stats': 1.3
},
}
最干净的方法是什么?
我可以为每个 MyObject 设置一个循环,使用序列化器一个一个地序列化每个 MyObject,并为此对象创建和更新字典,添加 'stats' 键。
我担心性能。
如果我只计算某些对象的统计值,混合 2 种输出怎么办?
您可以使用 SerializerMethodField
:
class MyObjectSerializer(ModelSerializer):
stat = SerializerMethodField()
class Meta:
model = MyObject
fields = ( 'name', 'score', 'stat' )
def get_stat(self, obj):
# obj is the model instance (it passes only one even if many=True)
# do calculations with obj and return the value
return None
如果 stat
字段使用 related/foreign 关键模型时性能是一个问题,您可以使用注释或 select_related
/prefetch_related
。使用注释更有效,但根据需要可能难以创建。
如果可以注释,您可以使用其他序列化程序字段,例如:
class MyObjectSerializer(ModelSerializer):
stat = FloatField(read_only=True)
class Meta:
model = MyObject
fields = ( 'name', 'score', 'stat' )
除了@kyell 写的,你还可以使用@属性装饰器和return你的计算数据在模型中创建一个属性,这个属性总是只读。
我正在将 Laravel PHP 代码移植到 Python Django/Django Rest Framework。
我的端点将输出 JSON.
我需要输出很多对象,但我需要为每个对象添加额外的计算值。 我怎样才能做到这一点?
比如我的模型是:
from django.db import models
from rest_framework.serializers import ModelSerializer
class MyObject(models.Model):
name = models.CharField(max_length=255)
score = models.IntegerField()
class MyObjectSerializer(ModelSerializer):
class Meta:
model = MyObject
fields = ( 'name', 'score' )
我使用 MyObject.objects.all()
(或过滤器)检索了一个查询集。
对于我的查询集中的每个 MyObject,我计算一个额外的值,称为 'stats',我想在我的 JSON 输出中输出它。
例如,如果我有 2 个对象 MyObject(name='foo',score='1') 和 MyObject(name='bar',score='2'),我将计算每个对象的统计值。
我的 JSON 输出应该是这样的:
{
{
'name': 'foo',
'score': 1,
'stats': 1.2
},
{
'name': 'bar',
'score': 2,
'stats': 1.3
},
}
最干净的方法是什么?
我可以为每个 MyObject 设置一个循环,使用序列化器一个一个地序列化每个 MyObject,并为此对象创建和更新字典,添加 'stats' 键。 我担心性能。
如果我只计算某些对象的统计值,混合 2 种输出怎么办?
您可以使用 SerializerMethodField
:
class MyObjectSerializer(ModelSerializer):
stat = SerializerMethodField()
class Meta:
model = MyObject
fields = ( 'name', 'score', 'stat' )
def get_stat(self, obj):
# obj is the model instance (it passes only one even if many=True)
# do calculations with obj and return the value
return None
如果 stat
字段使用 related/foreign 关键模型时性能是一个问题,您可以使用注释或 select_related
/prefetch_related
。使用注释更有效,但根据需要可能难以创建。
如果可以注释,您可以使用其他序列化程序字段,例如:
class MyObjectSerializer(ModelSerializer):
stat = FloatField(read_only=True)
class Meta:
model = MyObject
fields = ( 'name', 'score', 'stat' )
除了@kyell 写的,你还可以使用@属性装饰器和return你的计算数据在模型中创建一个属性,这个属性总是只读。