我正在将食谱组织者编写为课程的示例项目。除了使用一些非常基本的功能之外,我对DRF没有太多经验。这就是目标:
使用相关成分创建新配方。在创建配方对象的同时创建成分对象。
models.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
这样可以在数据库中成功创建配方对象和配料对象,但不会将配料列表与配方相关联。我认为这是因为当我运行ingredients_data = validated_data.pop('ingredients')
时,validated_data
字典会删除其成分,因此当我使用validated_data
创建新配方时,没有相关的成分。< / p>
然而,我似乎无法找到一种方法来保留与食谱相关的成分。
答案 0 :(得分:37)
我发现在创建所有未创建的对象之前,无法建立ManyToMany关系。 (参见Django Docs page on many-to-many relationships。)
这是工作代码:
<强> 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
根据@StevePiercy的要求,下面是我的update()
代码。 然而,我多年没有看过这个,如果它是正确的还是好的,我也不知道。我已经有一段时间没有使用过Python或Django了,所以请稍等一下:
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
答案 1 :(得分:8)
这是这个问题的一个小例子。
通过此更改代码的这一部分。
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
这是编辑方法,在您想要编辑时会导致错误。
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
这是一个带有示例的链接,这段代码类似于另一个答案,但是如果你想尝试代码,这里没有问题就是repo。祝好运! DRF Nested serializers