具有多对多关系的ModelForm:如果需要,如何自动创建新条目?

时间:2018-06-15 15:15:40

标签: django django-forms many-to-many

我有两个具有ManyToMany关系的模型:

class PizzaUpdateForm(forms.ModelForm):
    class Meta:
        model = Pizza
        fields=('name', 'toppings')
        widgets={'toppings': Select2TagWidget}

我有这个表格来更新披萨:

Select2TagWidget

django_select2导入def update_pizza(request, pk): pizza = Pizza.objects.get(pk=pk) if request.method == 'POST': form = PizzaUpdateForm(request.POST, instance=pizza) if form.is_valid(): form.save() else: form = PizzaUpdateForm(instance=pizza) return render(request, 'pizza/pizza_form.html', {'form': form, 'pizza': pizza}) 。我想用它来实现动态披萨顶部创建(听起来很酷,不是吗?)。

此表单用于此视图:

"illegal_topping" is not a valid value.

现在,它适用于预先注册的浇头,但我想允许我的用户通过相同的表单定义新的浇头,这就是为什么我首先使用select2。不幸的是,表格不会验证我现在是否这样做,这是可以预期的。

如果我尝试添加 illegal_topping ,会发生以下情况:

form['toppings'].value()

我认为我需要在调用form.is_valid()之前在if request.method == 'POST'块中迭代get_or_create,以便使用{{1}}或类似内容创建新的顶部。< / p>

但是,如果我这样做,则值是现有浇头ID和新浇头名称的混合。一切都是一个字符串,所以我不确定如何评估哪一个是新的浇头,哪些是预先存在的。

如果这些价值仅由浇头的名称组成,可能会很棒,但我不知道如何实现这一目标。

也许我的方法是完全错误的,因为我是网络开发和Django的新手,所以我真的很想得到你的意见。在我看来,这一定是一个相对常见的问题......但我找不到(或理解)帮助。我知道必须有一些我没有预料到的M2M问题,所以任何指导都非常受欢迎。

2 个答案:

答案 0 :(得分:0)

我想你允许用户选择已退出的配料或者可以创建新的配料,对吧? (create_top是用户请求新顶部的输入字段名称)

def update_pizza(request, pk):
    pizza = Pizza.objects.get(pk=pk)
    if request.method == 'POST':
        form = PizzaUpdateForm(request.POST, instance=pizza)
        if form.is_valid():
            ctoppings = []

            form = form.save(commit=False)
            if not request.POST.get['create_top'] = '':
                t, create = Topping.objects.get_or_create(name = request.POST.get['create_top'])
                temp_top = request.POST.getlist('toppings')
                for top in temp_top:
                    ctop = Topping.objects.get(name=top)
                    ctoppings.append(ctop)
                ctoppings.append(t)
                form.toppings.set(ctoppings)
            form.save()
    else:
        form = PizzaUpdateForm(instance=pizza)
    return render(request, 'pizza/pizza_form.html',
                  {'form': form, 'pizza': pizza})

看看这是否可以帮到你。

答案 1 :(得分:0)

我发现了一种肮脏的方式。

class PizzaUpdateForm(forms.ModelForm):
    class Meta:
        model = Pizza
        fields=('name', 'toppings')
        widgets={'toppings': Select2TagWidget}

    toppings = forms.ModelMultipleChoiceField(queryset=Topping.objects.all(),
                                              to_field_name='name',
                                              widget=Select2TagWidget,
                                              required=False)

def update_pizza(request, pk):
    pizza = Pizza.objects.get(pk=pk)
    if request.method == 'POST':
        form = PizzaUpdateForm(request.POST, instance=pizza)
        for topping_name in form['toppings'].value():
            topping, created = Topping.objects.get_or_create(name=topping_name)
            if created: topping.save()
        if form.is_valid():
            form.save()
    else:
        form = PizzaUpdateForm(instance=pizza)
    return render(request, 'pizza/pizza_form.html',
                  {'form': form, 'pizza': pizza})

但是,如果顶部创建逻辑不在视图中但在pizza.forms模块中,我觉得它会更糟糕。我想这就行了。