1
votes

Model:

class Person(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    
    def __str__(self):
        return self.first_name + ' ' + self.last_name
        
        
class Gender(models.Model):
    gender = models.CharField(max_length=1)
    
    def __str__(self):
        return self.gender
        
        
class Details(models.Model):
    name = models.ForeignKey(Person, on_delete=models.CASCADE)
    dob = models.DateField()
    gender = models.ForeignKey(Gender, on_delete=models.DO_NOTHING)

Serializer:

class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        model = Person
        fields = '__all__'


class GenderSerializer(serializers.ModelSerializer):

    class Meta:
        model = Gender
        fields = '__all__'


class ProfileSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Profile
        fields = ['name', 'dob', 'gender']

At present the output I get below output with the above in place:

[
    {
        "name": 1,
        "dob": "1990-05-19",
        "gender": 1
    }
]

where id 1 for Person = "John Smith" and id 1 for gender is "Male". I got several solutions on stackoverflow such as:

All of these methods work but then the Django Rest Framework makes the foreign keys as Read Only and the these fields are no longer seen in the DRF HTML Form. My question here is how to get to display foreign key field value instead of id ensuring DRF HTML Form still shows those fields as earlier

2

2 Answers

4
votes

Override the to_representation method of ProfileSerializer class

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ['name', 'dob', 'gender']

    def to_representation(self, instance):
        rep = super().to_representation(instance)
        rep['gender'] = GenderSerializer(instance.gender).data
        return rep
2
votes

If you don't wanto to override to_representation() , you can create a SerializerMethodField:

class ProfileSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()

    class Meta:
        model = Profile
        fields = ['name', 'dob', 'gender']

    # this method is called to get the value of field `name`
    def get_name(self, profile):
          return profile.name.name