Django REST 框架 : save related models in ModelViewSet

标签 django django-forms django-rest-framework formset

我正在尝试弄清楚如何使用 Django REST 框架保存相关模型。
在我的应用程序中,我有一个模型 Recipe有 2 个相关型号:RecipeIngredientRecipeStep .一个 Recipe对象必须至少有 3 个相关的 RecipeIngredient和 3 RecipeStep .在引入 REST 框架之前,我使用的是 Django CreateView有两个表单集,保存过程如下(遵循来自 form_valid() 的代码):

def save_formsets(self, recipe):
    for f in self.get_formsets():
        f.instance = recipe
        f.save()

def save(self, form):
    with transaction.atomic():
        recipe = form.save()
        self.save_formsets(recipe)
    return recipe

def formsets_are_valid(self):
        return all(f.is_valid() for f in self.get_formsets())

def form_valid(self, form):
    try:
        if self.formsets_are_valid():
            try:
                return self.create_ajax_success_response(form)
            except IntegrityError as ie:
                return self.create_ajax_error_response(form, {'IntegrityError': ie.message})
    except ValidationError as ve:
        return self.create_ajax_error_response(form, {'ValidationError': ve.message})
    return self.create_ajax_error_response(form)

现在我有我的 RecipeViewSet :
class RecipeViewSet(ModelViewSet):
    serializer_class = RecipeSerializer
    queryset = Recipe.objects.all()
    permission_classes = (RecipeModelPermission, )

使用 RecipeSerializer :
class RecipeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Recipe
        fields = (
            'name', 'dish_type', 'cooking_time', 'steps', 'ingredients'
        )

    ingredients = RecipeIngredientSerializer(many=True)
    steps = RecipeStepSerializer(many=True)

这些是相关的序列化程序:
class RecipeIngredientSerializer(serializers.ModelSerializer):
    class Meta:
        model = RecipeIngredient
        fields = ('name', 'quantity', 'unit_of_measure')

class RecipeStepSerializer(serializers.ModelSerializer):
    class Meta:
        model = RecipeStep
        fields = ('description', 'photo')

现在......我应该如何验证相关模型( RecipeIngredientRecipeStep )并在 RecipeViewSet 时保存它们的 create()方法被调用? ( is_valid() 中的 RecipeSerializer 实际上忽略了嵌套关系并仅报告与主模型 Recipe 相关的错误)。
目前我试图覆盖 is_valid() RecipeSerializer 中的方法,但不是那么简单......有什么想法吗?

最佳答案

这周我正在处理类似的问题,我发现 django rest framework 3 实际上支持嵌套可写序列化(http://www.django-rest-framework.org/topics/3.0-announcement/#serializers 在可写嵌套序列化子章节中。)

我不确定嵌套序列化器是否可写为默认值,所以我声明了它们:

ingredients = RecipeIngredientSerializer(many=True, read_only=False)
steps = RecipeStepSerializer(many=True, read_only=False)

你应该在 RecipeSerializer 中重写你的创建方法:
class RecipeSerializer(serializers.ModelSerializer):
    ingredients = RecipeIngredientSerializer(many=True, read_only=False)
    steps = RecipeStepSerializer(many=True, read_only=False)

    class Meta:
        model = Recipe
        fields = (
            'name', 'dish_type', 'cooking_time', 'steps', 'ingredients'
        )

    def create(self, validated_data):
        ingredients_data = validated_data.pop('ingredients')
        steps_data = validated_data.pop('steps')
        recipe = Recipe.objects.create(**validated_data)
        for ingredient in ingredients_data:
            #any ingredient logic here
            Ingredient.objects.create(recipe=recipe, **ingredient)
        for step in steps_data:
            #any step logic here
            Step.objects.create(recipe=recipe, **step)
        return recipe

如果这个结构 Step.objects.create(recipe=recipe, **step) 不起作用,也许你必须从steps_data/成分数据中分别选择代表每个字段的数据。

这是指向我之前(已实现的)堆栈问题/答案的链接:How to create multiple objects (related) with one request in DRF?

关于Django REST 框架 : save related models in ModelViewSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28458694/

相关文章:

python - 为什么 Django 1.8 和 1.7 中的 urls.py 不同?

python - 如何将多个图像插入博客文章而不是文件字段上传(Django 博客)

python - 必须使用 WorkoutList 实例作为第一个参数来调用未绑定(bind)方法 get_queryset() (什么也没得到)

python - 如何引发错误/返回 {"foo": ["This field is required."]} response in Django REST

django - Dj Rest Auth 自定义注册不起作用

python - 当查询返回Null(无对象)时如何在django模板中显示 "nothing found"?

django - 表单中 Django 模型浮点字段的本地化

python - Django 表单中的隐藏字段不在 cleaned_data 中

django 表单给出 : Select a valid choice. 该选项不是可用选项之一

django - 在 Django 模型中使用 Choices 时,为什么要设置 max_length?