我试图获取基于外键的数据。 让我们说我有这些模型:
# models.py
class Player(models.Model):
name = models.CharField(max_length = 64)
class Game(models.Model):
score = models.IntegerField()
player = models.ForeignKey('Player', models.DO_NOTHING, related_name='player', blank=False, null=False)
class InjuredPlayer(models.Model):
player = models.ForeignKey('Player', models.DO_NOTHING, blank=False, null=False)
我使用REST框架,所以我有这个序列化程序。我想添加一个属性,该属性是所有游戏分数与玩家序列化程序的总和。
# Serializer
class PlayerSerializer(serializers.ModelSerializer):
# Get the sum of Game scores of the player
# sum_of_scores = ________________
class Meta:
model = Player
# Use sum_of_scores as a field on the serializer
fields = ('activity', 'logo', 'sum_of_scores')
然后,想要做的是显示玩家列表及其得分总和,如果他们在InjuredPlayer上。所以在我的班上:
class PlayerList(APIView)
查询集应该类似于:
# I tried this
queryset = Player.objects.filter(injuredplayer__player=id)
如何过滤不在另一个表上的对象。 是否可以根据sum_of_scores订购列表?如果是这样,怎么样? 谢谢
答案 0 :(得分:2)
如果您想获得序列化程序中所有字段的总和,请使用 serializerMethodField
from django.db.models import Sum
# also import Game model
class PlayerSerializer(serializers.ModelSerializer):
sum_of_scores = serializers.SerializerMethodField()
class Meta:
model = Player
fields = ('id', 'name', 'sum_of_scores')
def get_sum_of_scores(self, obj):
return Game.objects.filter(player=obj).aggregate(Sum('score'))
注意强> 您的模型结构不是最佳的,您可以将 InjuredPlayer 模型和新字段移除到播放器,例如 is_injured 。并将其设置为默认值false。而且游戏模型的相关名称应该是“游戏”或其他东西。这样你就可以轻松反向引用。在您当前的结构中,要获得与玩家相关的所有游戏,您应该调用player.player.all()。如果你把它改成游戏,那将是player.games.all()
所以新结构应该是
# models.py
class Player(models.Model):
name = models.CharField(max_length = 64)
is_injured = models.BooleanField(dafault=False)
class Game(models.Model):
score = models.IntegerField()
player = models.ForeignKey('Player', models.DO_NOTHING, related_name='games', blank=False, null=False)
串行器变为
# Serializer
from django.db.models import Sum
class PlayerSerializer(serializers.ModelSerializer):
sum_of_scores = serializers.SerializerMethodField()
class Meta:
model = Player
fields = ('id', 'name', 'is_injured', 'sum_of_scores')
def get_sum_of_scores(self, obj):
return obj.games.all().aggregate(Sum('score'))