简体   繁体   中英

How to serialize joined tables if there are 2 Foreign Key to join the same table with Django Rest Framework?

I have a short model to store football teams and results of their matches. The Match model has a home_team_id and an away_team_id to identify the 2 teams, both of them are the Foreign Key for the Team model. I want to serialize the data from these 2 tables to have the following output:

[
 {
        "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')

I am receiving an error: 'Match' object has no attribute 'team_name', which is fair as in views.py the Match model has been selected,however I added team_name = serializers.StringRelatedField(many=True, read_only=True) in serializers. I tried this the other way around, with using the Team model in the serializer, based on the tutorial here: https://www.django-rest-framework.org/api-guide/relations/ , but it didn't work. I am not even sure how to differentiate the team names as it both uses the Team model.

The raw SQL this query just to make sure my question makes sense:

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

The solution is Simple whenever you want some computed value in your serializer, you can use serializers.SerializerMethodField() docs . In Your case, you can define your serializer as

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__' 

Also, a suggestion from my side, when declaring the attribute name for foreign key fields, don't use the _id suffix at the end because the ORM does it for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM