[英]Django Rest Framework writable nested serializers
我正在編寫一個食譜組織者作為一個班級的示例項目。 除了使用一些非常基本的功能之外,我對 DRF 的經驗並不多。 這是目標:
使用相關成分創建新配方。 在創建 Recipe 對象的同時創建 Ingredient 對象。
模型.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
序列化程序.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
創建一個新的食譜時,沒有關聯的成分。
但是,我似乎無法找到一種方法來保持與食譜相關的成分。
我發現在創建所有未創建的對象之前無法建立多對多關系。 (請參閱關於多對多關系的 Django 文檔頁面。)
這是工作代碼:
序列化程序.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
下面是這個問題的一個有用的例子。
像這樣更改那部分代碼:
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 嵌套序列化程序
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.