Django REST框架:将相关模型保存在ModelViewSet中 [英] Django REST framework: save related models in ModelViewSet

查看:72
本文介绍了Django REST框架:将相关模型保存在ModelViewSet中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to figure out how to save related models using Django REST framework. In my app I have a model Recipe with 2 related models: RecipeIngredient and RecipeStep. A Recipe object MUST have at least 3 related RecipeIngredient and 3 RecipeStep. Before the introduction of the REST framework I was using a Django CreateView with two formsets and the save process was the following (follow the code from 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)

这些是相关的序列化器:

and these are the related serializers:

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')

现在...我应该如何验证相关模型( RecipeIngredient RecipeStep )并在 RecipeViewSet create()方法被调用?( RecipeSerializer 中的 is_valid()实际上是忽略嵌套关系,仅报告与主模型 Recipe 相关的错误).目前,我尝试覆盖 RecipeSerializer 中的 is_valid()方法,但不是那么简单...知道吗?

Now... how I'm supposed to validate related models (RecipeIngredient and RecipeStep) and save them when RecipeViewSet's create() method is called? (is_valid() in RecipeSerializer is actually ignoring nested relationships and reporting only errors related to the main model Recipe). At the moment I tried to override the is_valid() method in RecipeSerializer, but is not so simple... any idea?

推荐答案

本周我正在处理类似的问题,我发现django rest框架3实际上支持嵌套的可写序列化(

I was dealing with similiar issue this week and I found out, that django rest framework 3 actually supports nested writable serialisation (http://www.django-rest-framework.org/topics/3.0-announcement/#serializers in subchapter Writable nested serialization.)

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

Im not sure if nested serialisers are writable be default, so I declared them:

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

,您应该在RecipeSerializer中重写您的创建方法:

and you should rewrite your create methon inside 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/Ingredients_data中分别选择代表每个字段的数据.

if this structure Step.objects.create(recipe=recipe, **step) wont work, maybe you have to select data representeng each field separatly from steps_data / ingredients_data.

这是我以前在栈上的(已解决的)问题/答案的链接:

This is link to my earlier (realted) question/answer on stack: How to create multiple objects (related) with one request in DRF?

这篇关于Django REST框架:将相关模型保存在ModelViewSet中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆