如果有 2 个外键与 Django Rest Framework 连接相同的 table,如何序列化连接的 table?
How to serialize joined tables if there are 2 Foreign Key to join the same table with Django Rest Framework?
我有一个短模型来存储足球队和他们的比赛结果。 Match 模型有一个 home_team_id 和一个 away_team_id 来标识 2 个团队,它们都是 Team 模型的外键。我想序列化这两个表中的数据以获得以下输出:
[
{
"home_team_id": 283584,
"home_team_name": "FC Bayern München"
"away_team_id": 61,
"away_team_name": "Chelsea FC"
"match_id": 12342
"home_team_goals": 1,
"away_team_goals": 2,
},
...
]
models.py
from django.db import models
class Team(models.Model):
team_id = models.IntegerField(primary_key=True)
team_name = models.CharField(max_length=200, blank=False, null=False)
#category_id = models.IntegerField(blank=False)
#value = models.IntegerField(blank=False)
def __str__(self):
return '%s' % (self.team_name)
class Match(models.Model):
match_id = models.IntegerField(primary_key=True)
home_team_id = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="home_team_id")
away_team_id = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="away_team_id")
home_team_goals = models.SmallIntegerField(blank=False)
away_team_goals = models.SmallIntegerField(blank=False)
views.py
@api_view(['GET'])
def full_list(request):
full = Match.objects.all()
serializer = TeamMatchesSerializer(full, many=True)
return Response(serializer.data)
serializers.py
class TeamMatchesSerializer(serializers.ModelSerializer):
team_name = serializers.StringRelatedField(many=True, read_only=True)
class Meta:
model = Match
fields = ('match_id', 'home_team_goals', 'away_team_goals', 'team_name')
我收到一条错误消息:'Match' 对象没有属性 'team_name',这很公平,因为 views.py 选择了匹配模型,但是我添加了 team_name = serializers.StringRelatedField(many=True, read_only=True) 在序列化器中。我尝试了另一种方法,在序列化程序中使用团队模型,基于此处的教程:https://www.django-rest-framework.org/api-guide/relations/,但它没有用。我什至不确定如何区分团队名称,因为它们都使用团队模型。
原始 SQL 这个查询只是为了确保我的问题有意义:
select home.team_id,
home.team_name,
away.team_id,
away.team_name,
a.match_id,
a.home_team_goals,
a.away_team_goals
from api_match a
inner join api_team home on home.team_id = a.home_team_id
inner join api_team away on away.team_id = a.away_team_id
只要你想在你的序列化器中计算一些值,解决方案很简单,你可以使用 serializers.SerializerMethodField()
docs。在您的情况下,您可以将序列化程序定义为
class TeamMatchesSerializer(serializers.ModelSerializer):
home_team_name = serializers.SerializerMethodField()
away_team_name = serializers.SerializerMethodField()
def get_home_team_name(self, obj):
return obj.home_team_id.team_name
def get_away_team_name(self, obj):
return obj.away_team_id.team_name
class Meta:
model = Match
fields = '__all__'
另外,我这边的一个建议,在声明外键字段的属性名时,不要在最后使用 _id
后缀,因为 ORM 会帮你完成。
我有一个短模型来存储足球队和他们的比赛结果。 Match 模型有一个 home_team_id 和一个 away_team_id 来标识 2 个团队,它们都是 Team 模型的外键。我想序列化这两个表中的数据以获得以下输出:
[
{
"home_team_id": 283584,
"home_team_name": "FC Bayern München"
"away_team_id": 61,
"away_team_name": "Chelsea FC"
"match_id": 12342
"home_team_goals": 1,
"away_team_goals": 2,
},
...
]
models.py
from django.db import models
class Team(models.Model):
team_id = models.IntegerField(primary_key=True)
team_name = models.CharField(max_length=200, blank=False, null=False)
#category_id = models.IntegerField(blank=False)
#value = models.IntegerField(blank=False)
def __str__(self):
return '%s' % (self.team_name)
class Match(models.Model):
match_id = models.IntegerField(primary_key=True)
home_team_id = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="home_team_id")
away_team_id = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="away_team_id")
home_team_goals = models.SmallIntegerField(blank=False)
away_team_goals = models.SmallIntegerField(blank=False)
views.py
@api_view(['GET'])
def full_list(request):
full = Match.objects.all()
serializer = TeamMatchesSerializer(full, many=True)
return Response(serializer.data)
serializers.py
class TeamMatchesSerializer(serializers.ModelSerializer):
team_name = serializers.StringRelatedField(many=True, read_only=True)
class Meta:
model = Match
fields = ('match_id', 'home_team_goals', 'away_team_goals', 'team_name')
我收到一条错误消息:'Match' 对象没有属性 'team_name',这很公平,因为 views.py 选择了匹配模型,但是我添加了 team_name = serializers.StringRelatedField(many=True, read_only=True) 在序列化器中。我尝试了另一种方法,在序列化程序中使用团队模型,基于此处的教程:https://www.django-rest-framework.org/api-guide/relations/,但它没有用。我什至不确定如何区分团队名称,因为它们都使用团队模型。
原始 SQL 这个查询只是为了确保我的问题有意义:
select home.team_id,
home.team_name,
away.team_id,
away.team_name,
a.match_id,
a.home_team_goals,
a.away_team_goals
from api_match a
inner join api_team home on home.team_id = a.home_team_id
inner join api_team away on away.team_id = a.away_team_id
只要你想在你的序列化器中计算一些值,解决方案很简单,你可以使用 serializers.SerializerMethodField()
docs。在您的情况下,您可以将序列化程序定义为
class TeamMatchesSerializer(serializers.ModelSerializer):
home_team_name = serializers.SerializerMethodField()
away_team_name = serializers.SerializerMethodField()
def get_home_team_name(self, obj):
return obj.home_team_id.team_name
def get_away_team_name(self, obj):
return obj.away_team_id.team_name
class Meta:
model = Match
fields = '__all__'
另外,我这边的一个建议,在声明外键字段的属性名时,不要在最后使用 _id
后缀,因为 ORM 会帮你完成。