如何同时保存外键对象和它的父对象

how to save ForeignKey object and its parent object at the same time

Angular 8、Django 3.我有两个模型RecipeIngredients。我在前端使用 ngModels 将数据发送到 Django 以创建 Recipe 模型。在一个页面上,当您单击 "submit" 时,所有 RecipeIngredients 数据都会发送到后端。

根据我读到的 ManyToOne 关系,models.ForeignKey 应该继续作为 "many" 一部分的模型。所以每个 Recipe 有 "many" Ingredients,所以我在 Ingredients 上有 Foreignkey

我的问题是,当我将所有这些数据发送到 Django 时,我的 Ingredients 没有被创建,因为 RecipeSerializer 上没有 ingredients 字段。

models.py

class Recipe(models.Model):
    name = models.CharField(max_length=30)


class Ingredients(models.Model):
    name = models.CharField(max_length=50)
    recipe = models.ForeignKey(Recipe, related_name='ingredients', on_delete=models.CASCADE)

views.py

class AddRecipe(generics.CreateAPIView):
    serializer_class = RecipeFullSerializer

serializers.py

class IngredientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ingredients
        fields = ['name']

class RecipeFullSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(many=True, read_only=True)
    class Meta:
        model = Recipe
        fields = ['name', 'ingredients']

示例数据

ingredients: Array(1)
0: {name: "23"}
length: 1
__proto__: Array(0)
name: "23"

我在后端得到一个 Ingredients 数据数组,只是不确定如何同时使用外键将其全部保存到 Recipes。我想我可以创建一个自定义视图来为我做这一切,但我认为会有一个基于 class 的视图可以做到这一点。

错误

AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `users.serializers.RecipeFullSerializer`, or set `read_only=True` on nested serializer fields.

您将成分设置为 read_only,因此它不会创建它们。如果你想保存它们,你需要删除它。

更新:另外,您需要重写创建方法。检查文档中的 Writing .create() methods for nested representations

会是这样的:

class RecipeFullSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(many=True)

    class Meta:
        model = Recipe
        fields = ['name', 'ingredients']

    def create(self, validated_data):
        ingredients = validated_data.pop('ingredients')
        recipe = Recipe.objects.create(**validated_data)
        for ingredient in ingredients:
            Ingredient.objects.create(recipe=recipe, **ingredient)

        return recipe