Phoenix
Phoenix

Reputation: 425

How to get specific fields from child serializers?

Say, there are two models:

class Model1(models.Model):
    r = models.CharField(max_length=200)

class Model2(models.Model):
    p = models.CharField(max_length=200)
    m = models.ForeignKey(Model1,on_delete=models.CASCADE)

The serializers are :

class Model1Serializer(serializers.Serializer):
    class Meta:
        model = Model1
        fields = '__all__'

class Model2Serializer(serializers.Serializer):
    class Meta:
         model = Model2
         fields = '__all__'

The given Model1 serializer returns the output as: { "id": 1, "r": "r_value" }

and model 2 serializer output is: { "id":1, "p: "p_value", "m": 1 }

The thing is that I also want the r value in the model2 serializer output. How to do that?

Upvotes: 1

Views: 1887

Answers (5)

Reza Torkaman Ahmadi
Reza Torkaman Ahmadi

Reputation: 3058

Simply use depth=1 in your serializer Meta. Like this:

class Model2Serializer(serializers.Serializer):
    class Meta:
         model = Model2
         fields = '__all__'
         depth = 1

This will go for a level of 1 into the Foreign keys that do exist in that model. (By the way, I don't recommend it for big models. But it's perfectly suitable for your situation)

Upvotes: 0

Try this

class Model1Serializer(serializers.Serializer):
   class Meta:
      model = Model1
      fields = '__all__'

class Model2Serializer(serializers.Serializer):
  r = Model1Serializer(many=True, source="model1_set")
  class Meta:
     model = Model2
     fields = '__all__'

Upvotes: 1

bkawan
bkawan

Reputation: 1361

1. If you want r as attrs of m

define Serializer class of specific Relational Field


class Model2Serializer(serializers.ModelSerializer):
    m = Model1Serializer()
    class Meta:
        model = Model2
        fields = '__all__'

output:


[
    {
        "id": 1,
        "m": {
            "id": 1,
            "r": "RED"
        },
        "p": "Light RED"
    },
    {
        "id": 2,
        "m": {
            "id": 1,
            "r": "RED"
        },
        "p": "Dark RED"
    }
]

2. If you want just r Using ReadOnlyField

You can use ReadOnlyField


class Model2Serializer(serializers.ModelSerializer):
    r = serializers.ReadOnlyField(source='m.r')

    class Meta:
        model = Model2
        fields = '__all__'

output:

[
    {
        "id": 1,
        "r": "RED",
        "p": "Light RED",
        "m": 1
    },
    {
        "id": 2,
        "r": "RED",
        "p": "Dark RED",
        "m": 1
    }
]

3. If you want just r Using SerializerMethodField()

You can you SerializerMethodField and ist read only as well


class Model2Serializer(serializers.ModelSerializer):
    r = serializers.SerializerMethodField()

    class Meta:
        model = Model2
        fields = '__all__'

    def get_r(self, instance):
        return instance.m.r

output:

[
    {
        "id": 1,
        "r": "RED",
        "p": "Light RED",
        "m": 1
    },
    {
        "id": 2,
        "r": "RED",
        "p": "Dark RED",
        "m": 1
    }
]

Upvotes: 1

jozo
jozo

Reputation: 4792

You need to specify new field with correct source - you can read more in docs.

Option 1: With class Serializer:

class Model2Serializer(serializers.Serializer):
    id = serializers.IntegerField()
    p = serializers.CharField()
    r = serializers.CharField(source='m.r')

    class Meta:
         model = Model2
         fields = '__all__'

Output: {'p': u'pppp', 'r': u'rrrrr', 'id': 1}

Option 2: With class ModelSerializer:

class Model2Serializer(serializers.ModelSerializer):
    r = serializers.CharField(source='m.r')

    class Meta:
         model = Model2
         fields = '__all__'

Output: {'p': u'pppp', 'r': u'rrrrr', 'm': 1L, u'id': 1}

Option 3: To include whole Model1:

class Model1Serializer(serializers.ModelSerializer):
    class Meta:
        model = Model1
        fields = '__all__'

class Model2Serializer(serializers.Serializer):
    m = Model1Serializer()

    class Meta:
        model = Model2
        fields = '__all__'

Output: {'m': OrderedDict([(u'id', 1), ('r', u'rrrrr')])}

Upvotes: 1

Endre Both
Endre Both

Reputation: 5740

DRF makes it quite easy if you already have a Model1Serializer for Model1:

class Model2Serializer(serializers.Serializer):
    m = Model1Serializer()
    class Meta:
         model = Model2
         fields = '__all__'

That should be it.

Upvotes: 0

Related Questions