Home > Software engineering >  How to get relate model without nested in Django rest framework?
How to get relate model without nested in Django rest framework?

Time:09-29

How to get a json with relate model but without nested in Django rest framework?

Code :

Models, Session and Athlete, Athlete models has foreign key relationship with Session

class Session(models.Model):
    Id = models.AutoField(primary_key=True)
    SessionNo = models.SmallIntegerField()
    WinTeam = models.SmallIntegerField(null=True)

class Athlete(models.Model):
    Id = models.AutoField(primary_key=True)
    Name = models.CharField(max_length=6)
    Age = models.SmallIntegerField()
    Session = models.ForeignKey(Session, on_delete=models.CASCADE, related_name='athletes')
    Status = models.SmallIntegerField()

Serializers

class SessionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Session
        fields = '__all__'

class AthleteSerializer(serializers.ModelSerializer):
    Session = SessionSerializer(read_only=True)

    class Meta:
        model = Athlete
        fields = ('Age', 'Status', 'Session')

And views:

def all_athletes(request):
    """
    Get all athletes list
    """
    queryset = Athlete.objects.all().select_related()
    serializer = AthleteSerializer(instance=queryset, many=True)
    return Response(serializer.data)

And the API result is :

[
    {
        "Age": 38,
        "Status": 1,
        "Session": {
            "Id": 13,
            "SessionNo": 1,
            "WinTeam": null
        }
    },
    {
        "Age": 26,
        "Status": 1,
        "Session": {
            "Id": 13,
            "SessionNo": 1,
            "WinTeam": null
        }
    },
    {
        "Age": 35,
        "Status": 2,
        "Session": {
            "Id": 13,
            "SessionNo": 1,
            "WinTeam": null
        }
    }
]

It works to get relate model, but I want relate models show without nested, how to do to fit my expectation ?

I expect the API result:

[
    {
        "Age": 38,
        "Status": 1,
        "Id": 13,
        "SessionNo": 1,
        "WinTeam": null
    },
    {
        "Age": 26,
        "Status": 1,
        "Id": 13,
        "SessionNo": 1,
        "WinTeam": null
    },
    {
        "Age": 35,
        "Status": 2,
        "Id": 13,
        "SessionNo": 1,
        "WinTeam": null
    }
]

CodePudding user response:

You could try SerializerMethodFields....

class AthleteSerializer(serializers.ModelSerializer):
    Id = serializers.SerialierMethodField(read_only=True)
    SessionNo = serializers.SerialierMethodField(read_only=True)
    WinTeam = serializers.SerialierMethodField(read_only=True)

    class Meta:
        model = Athlete
        fields = ('Age', 'Status', 'Id', 'SessionNo', 'WinTeam')
    
    def get_Id(self, obj):
        return obj.Session.id
    
    def get_SessionNo(self, obj):
        return obj.Session.SessionNo
    
    def get_WinTeam(self, obj):
        return obj.Session.WinTeam

And then remember to prefetch the Session relationship(s) in your view's queryset or else it will hit the database multiple times for those multiple fields

CodePudding user response:

You can override to_representation() in AthleteSerializer as well. With that you do not need SerialierMethodField.

def to_representation(self, value):
   ref = super().to_representation(value)
   session = ref.pop("Session")
   ref.update(**session)
   return ref
  • Related