Django Rest框架可写嵌套序列化程序

2024-06-16 11:39:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个食谱组织者作为一个班级的样本项目。除了使用一些非常基本的功能之外,我对DRF没有什么经验。目标是:

创建一个包含相关成分的新配方。在创建配方对象的同时创建配料对象。

型号.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创建新配方时,没有关联的成分。

然而,我似乎想不出一个方法来保持与配方相关的成分。


Tags: 对象nameselfdatareturnmodelsdef配方
2条回答

我发现在所有未创建的对象都被创建之前,无法建立多个关系。(见Django文档page on many-to-many relationships。)

这是工作代码:

序列化程序.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

更新:

根据@steppiercy的请求,下面是我的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

这里是一个链接,有一个例子,这段代码类似于另一个答案,但是如果你想尝试这段代码,这里没有问题的是回购协议。祝你好运! DRF Nested serializers

相关问题 更多 >