Home > Enterprise >  DRF ManyToMany instances add not create
DRF ManyToMany instances add not create

Time:07-06

I have the following code of my model:

class Recipe(BaseModel):
    """
    Recipe model class using for contains recipe, which can be sent to chat
    with coach. In text recipe contains RecipeStep.
    """
    ingredients = models.ManyToManyField(
        Product,
        verbose_name=_("ingredients"),
        related_name="ingredients"
    )
    portion_size = models.PositiveSmallIntegerField(
        _("portion size")
    )

    # TODO: add "add_to_meal" logic (user can add recipe to his meal).
    # it can be reached by using M2M with user and creating new relation for 
    # user and recipe on user click on special button.

    def __str__(self) -> str:
        return f"recipe \"{self.title}\""
    
    def __repr__(self) -> str:
        return f"Recipe({self.pk=}, {self.title=}, {self.is_published=})"
    
    class Meta:
        verbose_name = _("recipe")
        verbose_name_plural = _("recipes")

BaseModel is abstract class, that has basic structure of Article-like models (title, description, published_at, etc.).

And the following code of serializers for model:

class RecipeSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField(read_only=True)
    title = serializers.CharField(min_length=1, max_length=200, required=True)
    ingredients = ProductSerializer(many=True, read_only=False)
    portion_size = serializers.IntegerField(min_value=0, required=True)
    is_published = serializers.BooleanField(required=False, default=False)
    publish_date = serializers.DateField(
        allow_null=True,
        required=False,
        read_only=True
    )
    image_add_id = serializers.UUIDField(required=True)
    
    def create(self, validated_data):
        validated_data.pop('image_add_id', None)
        return super().create(validated_data)

    class Meta:
        model = Recipe
        fields = "__all__"

I need to create Recipe with passing list of existing ingredient pks, and not create new ingredients like:

{
    ...
    "ingredients": [
        "d6c065a2-7f80-47f3-8c0e-186957b07269",
        "4b8359d2-073a-4f41-b3cc-d8d2cfb252d5",
        "b39e4cc2-18c3-4e4a-880a-6cb2ed556160",
        "603e2333-0ddf-41f1-99f5-3dfe909eb969"
    ]

}

How should I do this?

CodePudding user response:

You are using model serializers so you don't have to redefine serializers fields. Also, since you are adding many related field you have to add after model instance created as follow

class RecipeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Recipe
        fields = '__all__'
    
    def create(self, validated_data):
        ingredients = validated_data.pop('ingredients')
        instance = super().create(validated_data)
        for ingredient in ingredients:
            instance.ingredients.add(ingredient)
        return instance
            
  • Related