我有两个具有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问题,所以任何指导都非常受欢迎。
答案 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
模块中,我觉得它会更糟糕。我想这就行了。