【问题标题】:How to serialize joined tables if there are 2 Foreign Key to join the same table with Django Rest Framework?如果有 2 个外键与 Django Rest Framework 连接同一个表,如何序列化连接的表?
【发布时间】:2020-09-20 20:37:28
【问题描述】:

我有一个简短的模型来存储足球队和他们的比赛结果。 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=真的)在序列化程序中。我根据这里的教程:https://www.django-rest-framework.org/api-guide/relations/,在序列化程序中使用 Team 模型,但它没有用。我什至不确定如何区分团队名称,因为它都使用团队模型。

这个查询的原始 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

【问题讨论】:

    标签: python django django-models django-rest-framework django-serializer


    【解决方案1】:

    解决方案很简单,只要您想在序列化程序中获得一些计算值,您可以使用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 会为您完成。

    【讨论】:

    • 谢谢。它完美地工作。当我检查 TablePlus 中的表格时,我也注意到了 _id。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2019-08-02
    • 1970-01-01
    • 2017-06-22
    • 2012-01-24
    相关资源
    最近更新 更多