16

I am currently having trouble executing two layered nesting with Django rest framework. I have read the DRF docs with nested relationships here http://www.django-rest-framework.org/api-guide/relations/ and have successfully done the first layer which is to show styles with many colors in JSON. Not sure how to chain another layer though. Any help would be appreciated. Thanks in advance!

The current output looks like this:

[{
    "name": "AAA123",
    "colors": [
        {
            "name": "White"
        }
    ]
},
{
    "name": "BBB222",
    "colors": [
        {
            "name": "White"
        },
        {
            "name": "Pink"
        },
        {
            "name": "Blue"
        }
    ]
}]

The wanted output should be like this:

[{
    "name": "AAA123",
    "colors": [
        {
            "name": "White",
            "sizes": [{name: "S"}, {name: "M"}]
        }
    ]
},
{
    "name": "BBB222",
    "colors": [
        {
            "name": "White",
            "sizes": [{name: "XS"}, {name: "S"}]
        },
        {
            "name": "Pink"
            "sizes": [{name: "XL"}, {name: "XXL"}]
        },
        {
            "name": "Blue"
            "sizes": [{name: "L"}, {name: "XL"}]
        }
    ]
}]

Specifically, I would like to show that each style has a set of colors attributed to it, and each style-color combination has a set of sizes attributed to it.

Below is my current serializers.py and models.py I've used the intermediate table because I plan to add further complexities in the future (e.g. in style-color I would like to attach location of the colored picture and in style-color-size, I will attach measurements)

serializers.py

class ColorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Color
        fields = ['name']


class SizeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Size
        fields = ['name']


class StyleSerializer(serializers.ModelSerializer):
    colors = ColorSerializer(many=True, read_only=True)

    class Meta:
        model = Style
        fields = ['name', 'colors']

models.py

class Style(models.Model):
    name = models.CharField(max_length=36, unique=True)
    colors = models.ManyToManyField('Color', through='StyleColor')



class Color(models.Model):
    name = models.CharField(max_length=36, unique=True)



class Size(models.Model):
    name = models.CharField(max_length=12, unique=True)



class StyleColor(models.Model):
    style = models.ForeignKey('Style', on_delete=models.CASCADE)
    color = models.ForeignKey('Color', on_delete=models.CASCADE)
    sizes = models.ManyToManyField('Size', through='StyleColorSize')

    class Meta:
        unique_together = ('style', 'color')



class StyleColorSize(models.Model):
    style_color = models.ForeignKey('StyleColor', on_delete=models.CASCADE)
    size = models.ForeignKey('Size', on_delete=models.CASCADE)

    class Meta:
        unique_together = ('style_color', 'size')
rahul singh Chauhan
  • 323
  • 1
  • 4
  • 15
柳 Lau
  • 443
  • 1
  • 4
  • 15
  • Can you add the serializer classes you are using now, also add expected and current oputputs – JPG Jul 05 '18 at 03:52
  • Hi @JerinPeterGeorge, thanks for taking the time to try and answer my question. Added your requested details in edit. Also, I'm thinking maybe I'm wrong in structuring my model. Not sure if sizes should be under Style or StyleColor. – 柳 Lau Jul 05 '18 at 04:19

2 Answers2

27

Thanks for all those who tried to answer. Got inspiration from the answer this link in case anyone gets into the same trouble as I did. Include intermediary (through model) in responses in Django Rest Framework.

class StyleSerializer(serializers.ModelSerializer):
    colors = StyleColorSerializer(source='stylecolor_set',
                                  many=True, read_only=True)

    class Meta:
        model = Style
        fields = ('name', 'colors')
柳 Lau
  • 443
  • 1
  • 4
  • 15
0

serializers.py

class ColorSerializer(serializers.ModelSerializer):

    class Meta:
        model = Color
        fields = '__all__'

class StyleSerializer(serializers.ModelSerializer):
    color = ColorSerializer() # each style has a set of colors attributed to it

    class Meta:
        model = Style
        fields = '__all__'

class SizeSerializer(serializers.ModelSerializer):

    class Meta:
        model = Size
        fields = '__all__'

class StyleColorSerializer(serializers.ModelSerializer):
    size = SizeSerializer() # each style-color combination has a set of sizes attributed to it

    class Meta:
        model = StyleColor
        fields = '__all__'

Because your models are too complex, I'm afraid the code above didn't fit that well.

To be more general, if you wanna attach the queryset of B model at the same time when you fetch the queryset of A model (which has a relationship with B model), you have to define the BSerializer() in the class of ASerializer().

mrhaoji
  • 336
  • 5
  • 19
  • 1
    Hi, I edited your answer to show many=True, read_only=True. However even with this, it only shows until the list of colors under each style while still not showing 'sizes' for each color. Not sure how to link the 'StyleColorSerializer' back to 'Style' – 柳 Lau Jul 05 '18 at 07:12