Getting serialized grandparent from ManyToMany relation DRF

Viewed 124

I'm struggling to serialize the grandparent(s) of a ManyToMany relation in my models. In the product serializer, i want to list the top level Category based on the SubCategory selected on the Product. My code is structured like this:

models.py

class Category(models.Model):
    
    ...
    name = models.CharField(
        _('category name'), 
        max_length=255, 
        unique=False
    )
    ...

class SubCategory(models.Model):
    parent = models.ForeignKey(
        Category, 
        on_delete=models.CASCADE, 
        related_name='children', 
    )
    name = models.CharField(
        _('category name'), 
        max_length=255, 
        unique=False
    )
    ...

class Product(models.Model):

    name = models.CharField(
        _('product name'),
        max_length=255,
        unique=True
    )
    category = models.ManyToManyField(
        SubCategory,
        related_name='products'
    )
    ...

serializers.py

class CategorySerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Category
        fields = ['name']


class ProductsSerializer(serializers.ModelSerializer):

    ...
    category = serializers.StringRelatedField(read_only=True, many=True)
    parent_category = CategorySerializer(read_only=True, source='category.parent', many=True)
    ...

    class Meta:
        model = Product
        fields = (
            ...
            'parent_category',
            'category',
            ...
        )

Currently the field parent_category does not show up in the json-response.

Edit: serializers.py:

class ProductCategorySerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Category
        fields = ['name']

class ProductSubCategorySerializer(serializers.ModelSerializer):

    class Meta:
        model = SubCategory
        fields = ['name']

class ProductsSerializer(serializers.ModelSerializer):

    ...
    subcategory = ProductSubCategorySerializer(many=True, source='category')
    category = ProductCategorySerializer()
    ...

    class Meta:
        model = Product
        fields = (
            ...
            'category',
            'subcategory',
            ...
        )

Current output:

[
    {
        "subcategory": [
            {
                "name": "sub category name",
                "category": {
                    "name": "main category name"
                }
            },
        ],
    }
]

wished output:

[
    {
        "category": [
            {
                "name": "main category name"
            },
            ...
        ],
        "subcategory": [
            {
                "name": "sub category name",
            },
            ...
        ],
    }
]
1 Answers

The full serializers setup would have to be like this:

class ProductCategorySerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Category
        fields = ['name']

class ProductSubCategorySerializer(serializers.ModelSerializer):
    category = ProductCategorySerializer(source="parent")

    class Meta:
        model = SubCategory
        fields = ['name', 'category']

class ProductsSerializer(serializers.ModelSerializer):

    ...
    subcategory = ProductSubCategorySerializer(many=True, source='category')
    ...

    class Meta:
        model = Product
        fields = (
            ...
            'subcategory',
            ...
        )
Related