Compro Prasad
Compro Prasad

Reputation: 162

Nested foreign key serializer in django not working

Part of models.py:

class FoodCuisine(models.Model):
    cuisine = models.CharField(max_length=64)

    def __str__(self):
        return self.cuisine


class CuisineTypes(models.Model):
    cuisine_types = models.CharField(max_length=64)
    cuisine = models.ForeignKey(FoodCuisine, on_delete=models.CASCADE)

    def __str__(self):
        return self.cuisine_types

    class Meta:
        ordering = ('cuisine_types',)


class Food(models.Model):
    name = models.CharField(max_length=192)
    veg = models.BooleanField(default=0)
    cuisine_type = models.ForeignKey(CuisineTypes, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    def _cuisine(self):
        return self.cuisine_type.cuisine

serializers.py:

class FoodSerializer(serializers.ModelSerializer):
    class Meta:
        model = Food
        fields = ('name', 'veg')


class CuisineTypesSerializer(serializers.ModelSerializer):
    foods = FoodSerializer(many=True, read_only=True, source='food_set')
    class Meta:
        model = CuisineTypes
        fields = ('cuisine_types', 'foods')


class FoodCuisineSerializer(serializers.ModelSerializer):
    cuisine_type = CuisineTypesSerializer(many=True, read_only=True, source='cuisinetypes_set')
    class Meta:
        model = FoodCuisine
        fields = ('cuisine', 'cuisine_type')

I want the FoodCuisineSerializer to return a nested list which will have all the food items categorized by their respective cuisine types and their cuisines.

The categorization is straight forward, having a list of cuisines in the first level, cuisine types in the second and food items in the third level.

Problem is that FoodCuisineSerializer only returns the first level only i.e. only the list of cuisines are shown. But I want the full nested list of food items as given in the previous paragraph.

Edit 1:

https://pastebin.com/dmVbyS0G is what I got from Django shell.

Edit 2:

If I write

>>> y = FoodCuisineSerializer(FoodCuisine.objects.get(id=2))
>>> y.cuisine_type
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'FoodCuisineSerializer' object has no attribute 'cuisine_type'

Why do I get the above error?

Edit 3:

Got the source in the right place but now I am getting:

>>> y = FoodCuisineSerializer(FoodCuisine.objects.get(id=2))
>>> y.data # I get the desired result having OrderedDict
>>> y = FoodCuisineSerializer(FoodCuisine.objects.all())
>>> y.data
[Error]

[Error]: https://pastebin.com/0DW28qv4 Whats next?

Upvotes: 2

Views: 2054

Answers (1)

JPG
JPG

Reputation: 88459

Set source='cuisinetypes_set' while serializeing the queryset as,

class FoodCuisineSerializer(serializers.ModelSerializer):
    cuisine_type = CuisineTypesSerializer(many=True, read_only=True, source='cuisinetypes_set')

    class Meta:
        model = FoodCuisine
        fields = ('cuisine', 'cuisine_type')


Reference
1. reverse relationship
2. source in DRF-Serializer


UPDATE 1
Since FoodCuisine.objects.all() is a QuerySet (list type object), you should pass many=True in serializer, as

y = FoodCuisineSerializer(FoodCuisine.objects.all(), many=True)

Upvotes: 4

Related Questions