简体   繁体   English

Django Rest Framework 可写嵌套序列化程序

[英]Django Rest Framework writable nested serializers

I'm writing a recipe organizer as a sample project for a class.我正在编写一个食谱组织者作为一个班级的示例项目。 I'm not very experienced with DRF other than using some very basic functionality.除了使用一些非常基本的功能之外,我对 DRF 的经验并不多。 Here's the objective:这是目标:

Create a new Recipe with associated Ingredients.使用相关成分创建新配方。 Create the Ingredient objects at the same time as creating the Recipe object.在创建 Recipe 对象的同时创建 Ingredient 对象。

models.py:模型.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序列化程序.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

This successfully creates the Recipe object AND the Ingredients objects in the database, but doesn't associate the list of Ingredients with the Recipe.这成功地在数据库中创建了配方对象和成分对象,但不会将成分列表与配方相关联。 I assume this is because when I run ingredients_data = validated_data.pop('ingredients') , the validated_data dictionary gets its Ingredients removed, so when I create a new Recipe using validated_data , there aren't associated ingredients.我认为这是因为当我运行ingredients_data = validated_data.pop('ingredients')validated_data字典删除了它的成分,所以当我使用validated_data创建一个新的食谱时,没有关联的成分。

However I can't seem to figure out a way to keep ingredients associated with the recipe.但是,我似乎无法找到一种方法来保持与食谱相关的成分。

I figured out that ManyToMany relationships can't be established until all of the uncreated objects have been created.我发现在创建所有未创建的对象之前无法建立多对多关系。 (See the Django Docs page on many-to-many relationships .) (请参阅关于多对多关系的 Django 文档页面。)

Here's the working code:这是工作代码:

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

UPDATE:更新:

Per request of @StevePiercy, below is my update() code.根据@StevePiercy 的请求,下面是我的update()代码。 However , I haven't looked at this in years and have no idea whatsoever if it is correct or good.但是,我多年没有看过这个,也不知道它是正确的还是好的。 I haven't been working in Python or Django for some time now, so take this with a grain of salt:我已经有一段时间没有在 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

Below is a helpful example for this question.下面是这个问题的一个有用的例子。

Change that part of code like this:像这样更改那部分代码:

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

And this is the method to edit, cause an error when you want to edit.这就是编辑的方法,当你想编辑时会导致错误。

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

Here is a link with an example.这是一个带有示例的链接。 This code is similar to another answer, but if you want to try the code without any problems, you can use this repo.此代码类似于另一个答案,但如果您想尝试该代码而没有任何问题,则可以使用此 repo。 Good luck!祝你好运! DRF Nested serializers DRF 嵌套序列化程序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM