pyramidface
pyramidface

Reputation: 1277

django rest framework: How can I display m2m and foreignkey fields besides id?

I went through the drf site's quickstart tutorial with my own models that contain a lot of m2m and foreignkey relationships. Some of my m2m relationships refer to the same model through the use of 'self'. Now when I look at my api for those m2m and foreignkey relationships, I'm seeing only id numbers instead of other information. How can I change this to contain useful information? Also, how can I place a limit on how deep the information gets displayed? I feel like if I can get other information to be displayed other than id, the m2m relationships could go on forever.

Anyway, here's a snippet of what I can see now: I'd like the appearance and relatives_many to show json of the model, or at least just have the name field displayed in addition to the id. Thanks for the help!

{
    "id": 97, 
    "name": "Ancient Sleeping Magi of Life Giving's mother", 
    "full_name": "Ancient Sleeping Magi of Life Giving's mother", 
    "sex": "Female", 
    "link": "http://adventuretime.wikia.com/wiki/Ancient_Sleeping_Magi_of_Life_Giving%27s_mother", 
    "image": "http://img2.wikia.nocookie.net/__cb20130408224627/adventuretimewithfinnandjake/images/0/0b/Magi%27s_parents1.png", 
    "species": [], 
    "appearance": [
        245
    ], 
    "relatives_many": [
        96, 
        92, 
        94, 
        705
    ]
},

Part of my models.

class Episode(models.Model):
    title = models.CharField(max_length=80)
    description = models.TextField(blank=True)
    season_number = models.PositiveSmallIntegerField(blank=True, null=True)
    episode_number = models.PositiveSmallIntegerField(blank=True, null=True)

    def __unicode__(self):
        return u"{}".format(self.title)

class Character(models.Model):
    name = models.CharField(max_length=80)
    full_name = models.CharField(max_length=120)
    sex = models.CharField(max_length=100, blank=True)
    species = models.ManyToManyField(Species, related_name="characters", blank=True)
    link = models.URLField(blank=True)
    appearance = models.ManyToManyField(Episode, related_name="characters", blank=True)
    image = models.URLField(blank=True)
    relatives_many = models.ManyToManyField('self', related_name="characters", blank=True)

    def __unicode__(self):
        return u"{}".format(self.name)

Serializers. I've tried setting the fields=("something",....) but that doesn't change how ids are displayed.

class CharacterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Character

class SpeciesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Species

Views.

class CharacterViewSet(viewsets.ModelViewSet):
    queryset = Character.objects.all()
    serializer_class = CharacterSerializer

class SpeciesViewSet(viewsets.ModelViewSet):
    queryset = Species.objects.all()
    serializer_class = SpeciesSerializer

EDIT Following sax's suggestions, I get this:

 {
    "relatives": [
        {
            "id": 38, 
            "name": "Ice King", 
            "full_name": "Ice King", 
            "sex": "Male", 
            "link": "http://adventuretime.wikia.com/wiki/Ice_King", 
            "image": "http://img3.wikia.nocookie.net/__cb20120921153231/adventuretimewithfinnandjake/images/6/64/Original_Ice_King.png", 
            "species": [
                10, 
                12, 
                14
            ], 
            "appearance": [
                42,
                23

            ]
        }
    ], 
    "id": 42, 
    "name": "Princess Monster Wife", 
    "full_name": "", 
    "sex": "", 
    "link": "", 
    "image": "", 
    "species": [], 
    "appearance": []
}, 

Upvotes: 1

Views: 599

Answers (1)

sax
sax

Reputation: 3806

try this, it's not tested but similar code works for me:

 class ChildCharacterSerializer(serializers.ModelSerializer):
    class Meta:
         model = Character
         exclude = ('relatives_many',)   


 class CharacterSerializer(serializers.ModelSerializer):
    relatives = serializers.SerializerMethodField('get_relatives')

    class Meta:
         model = Character

    def get_relatives(self, character):
        qs = character.characters.all()
        serializer = ChildCharacterSerializer(instance=qs, 
                                              many=True, context=self.context)
        return serializer.data

or if you don't need special filters:

 class CharacterSerializer(serializers.ModelSerializer):
    relatives_many = ChildCharacterSerializer()

Upvotes: 3

Related Questions