pythondjango-modelsdjango-rest-frameworkdjango-serializerdjango-related-manager

How to Serialize an additional field using ManyToMany relationship with intermediary model in Django Rest Framework?


I am trying to add field amount into Ingredient model, by creating an intermediary model IngredientAmount. But I am struggling with serialization.

The response should look like this:

"results": [
......
         "ingredients": [
          {
            "id": 0,
            "name": "Potato",
            "measurement_unit": "kg",
            "amount": 1
             }
         ],
....
]

I am using IngredientAmountSerializer(serializers.ModelSerializer), but Django says that I am in 'Ingredient' object and it has no attribute 'amount'.

what am I doing wrong?

models

    class Ingredient(models.Model):
    name = models.CharField(max_length=200)
    measurement_unit = models.CharField(max_length=200)

    class Meta:
        ordering = ['id']

    def __str__(self):
        return self.name


class IngredientAmount(models.Model):
    ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE,
                                   related_name='ingredient_amount')
    recipe = models.ForeignKey('Recipe', on_delete=models.CASCADE,
                               related_name='ingredient_amount')
    amount = models.SmallIntegerField(
        validators=(
            validators.MinValueValidator(
                1, 'add amount'),))


class Recipe(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    ingredients = models.ManyToManyField(
        Ingredient, through=IngredientAmount,
        through_fields=('recipe', 'ingredient', ),
        )
    tags = models.ManyToManyField(Tag, blank=True, related_name='recipe')
    image = models.ImageField()
    name = models.CharField(max_length=200)
    text = models.TextField()
    cooking_time = models.PositiveSmallIntegerField(
        validators=(
            validators.MinValueValidator(1, message='choose time'),
                   ),
                )

serializers

class IngredientAmountSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='ingredient.name', read_only=True)
    measurement_unit = serializers.IntegerField(source='ingredient.measurement_unit', read_only=True)
    class Meta:
        model = IngredientAmount
        fields = ('id', 'name', 'measurement_unit', 'amount' )


class RecipeSerializer(serializers.ModelSerializer):
    author = AuthorSerializer()
    tags = TagSerializer(read_only=True, many=True)
    image = Base64ImageField(required=True)
    ingredients = IngredientAmountSerializer( read_only=True, many=True)

    class Meta:
        model = Recipe
        fields = ('id', 'tags', 'author', 'name', 'image', 'text',
                  'cooking_time', 'ingredients')

Solution

  • I gues the problem is, you are trying to serialize Ingredient model with IngredientAmountSerializer when in it Meta model is IngredientAmount, and not Ingredient.

    Update: If you want serialize IngredientAmount, try to use source

    class RecipeSerializer(serializers.ModelSerializer):
        ...
        ingredients = IngredientAmountSerializer(source='ingredientamount_set', read_only=True, many=True)