Serializadores nesteds grabables de Django Rest Framework

Estoy escribiendo un organizador de recetas como un proyecto de muestra para una clase. No tengo mucha experiencia con DRF aparte de usar alguna funcionalidad muy básica. Aquí está el objective:

Crear una nueva receta con ingredientes asociados. Cree los objetos Ingredientes al mismo tiempo que crea el objeto Receta.

modelos.py:

class Ingredient(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Recipe(models.Model): name = models.CharField(max_length=100) description = models.TextField(blank=True, null=True, help_text="This is a quick description of your recipe") directions = models.TextField(help_text="How to make the recipe") ingredients = models.ManyToManyField(Ingredient) def __str__(self): return self.name 

serializers.py

 class IngredientSerializer(serializers.ModelSerializer): class Meta: model = Ingredient class RecipeSerializer(serializers.ModelSerializer): ingredients = IngredientSerializer(many=True) class Meta: model = Recipe def create(self, validated_data): ingredients_data = validated_data.pop('ingredients') recipe = Recipe.objects.create(**validated_data) for ingredient_data in ingredients_data: Ingredient.objects.create(**ingredient_data) return recipe 

Esto crea con éxito el objeto Receta Y los objetos Ingredientes en la base de datos, pero no asocia la lista de Ingredientes con la Receta. Supongo que esto es porque cuando ejecuto ingredients_data = validated_data.pop('ingredients') , el diccionario validated_data elimina sus ingredientes, por lo que cuando creo una nueva receta utilizando validated_data , no hay ingredientes asociados.

Sin embargo, parece que no puedo encontrar una manera de mantener los ingredientes asociados con la receta.

Me di cuenta de que las relaciones ManyToMany no se pueden establecer hasta que se hayan creado todos los objetos no creados. (Consulte la página de Django Docs sobre relaciones de muchos a muchos ).

Aquí está el código de trabajo:

serializers.py

 class RecipeSerializer(serializers.ModelSerializer): ingredients = IngredientSerializer(many=True) class Meta: model = Recipe def create(self, validated_data): ingredients_data = validated_data.pop('ingredients') recipe = Recipe.objects.create(**validated_data) for ingredient in ingredients_data: ingredient, created = Ingredient.objects.get_or_create(name=ingredient['name']) recipe.ingredients.add(ingredient) return recipe 

ACTUALIZAR:

Por solicitud de @StevePiercy, a continuación está mi código de update() . Sin embargo , no lo he visto en años y no tengo idea de si es correcto o bueno. No he estado trabajando en Python o Django por algún tiempo, así que toma esto con un grano de sal:

 def update(self, instance, validated_data): ingredients_data = validated_data.pop('ingredients') instance.name = validated_data.get('name', instance.name) instance.description = validated_data.get('description', instance.description) instance.directions = validated_data.get('directions', instance.directions) instance.photo = validated_data.get('photo', instance.photo) ingredients_list = [] for ingredient in ingredients_data: ingredient, created = Ingredient.objects.get_or_create(name=ingredient["name"]) ingredients_list.append(ingredient) instance.ingredients = ingredients_list instance.save() return instance 

Este es un pequeño ejemplo con esta pregunta.

Cambia esa parte del código por esto.

  def create(self, validated_data): ingredients_data = validated_data.pop('ingredients') recipe = Recipe.objects.create(**validated_data) for ingredient in ingredients_data: ingredient, created = Ingredient.objects.get_or_create(name=ingredient['name']) recipe.ingredients.add(ingredient) return recipe 

Y este es el método para editar, causa un error cuando quieres editar.

  def update(self, instance, validated_data): ingredients_data = validated_data.pop('ingredients') instance.name = validated_data['name'] instance.description = validated_data['description'] instance.directions = validated_data['directions'] for ingredient in ingredients_data: ingredient, created = Ingredient.objects.get_or_create(name=ingredient['name']) recipe.ingredients.add(ingredient) return instance 

Aquí hay un enlace con un ejemplo, este código es similar a otras respuestas, pero si desea probar el código, sin problemas aquí está el repo. ¡Buena suerte! DRS serializadores nesteds