我无法使用正确的代码,但是我发现了披萨/浇头的问题,并且问题很近,因此我正在对其进行修改以询问我的问题。 Django ModelForm for Many-to-Many fields
我们有很棒的披萨和浇头。假设我们经营连锁商店,但并非所有商店都包含所有成分。这意味着我们需要一个Store类,该类具有一个位置,并且浇头的位置很多。然后让我们下一个订单,该订单引用一家商店并且在Pizza上有很多内容,因为您经常订购多个。
models.py
from django import models
class Topping(models.Model):
name = models.TextField()
class Pizza(models.Model):
size = models.TextField()
toppings = models.ManyToManyField(Topping)
class Restaraunt(models.Model):
name = models.TextField()
toppings = models.ManyToManyField(Topping)
class Order(models.Model):
customer = models.ForeignKey('User')
location = models.ForeignKey(Restaraunt)
pizzas = models.ManyToManyField(Pizza)
表格
from django import forms
from django.forms import ModelForm
from models import *
class PizzaForm(ModelForm):
class Meta:
model = Pizza
toppings = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple(),
queryset=Topping.objects.all()
)
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.forms.models import modelformset_factory
from django.forms import CheckboxSelectMultiple
from models import *
from forms import *
def order_pizzas(request, order_id):
order_id = int(order_id)
order = get_object_or_404(Order, id=order_id)
restaraunt = order.restaraunt
PizzaFormSet = modelformset_factory(Pizza, form=PizzaForm, extra=1)
pizza_form = PizzaFormSet(request.POST or None)
return render(request, "place_order.html", {
'restaraunt': restaraunt,
'pizza_form': pizza_form,
})
如果这些没有实际运行,请不要打我太多。就像我说的那样,由于种种原因我不能在此处发布真实的代码,部分原因是它太庞大了。
为了本示例的目的,假定该人员已经将餐厅放置在离他们家最近的位置并开始订购过程。
我尝试过使用正确的名称和选项将小部件传递给modelformset_factory,但这种方式并未传播。
widgets = {'toppings':
CheckboxSelectMultiple(
choices=[t.id for t in restaraunt.toppings.all().order_by('-id')]
)}
我还尝试扩展BaseModelFormSet以传递额外的数据,并尝试将其输入到PizzaForm中,但是我被卡住了。
基本上,我可以说我需要以某种方式将信息从视图传播到表单集再传播到表单,以便可以正确初始化表单上的查询集。我只是不知道该怎么做。
因此,这是我找到的最接近的答案,但我似乎无法确定如何使它正常工作:
Django filter ModelFormSet field choices... different from limiting the Formset's queryset
回应有人要badge我张贴不工作的例子
关键是,我不是要别人张贴完全能解决我的问题的10行代码,而是要显示我所缺乏的知识。我知道我生成了PizzaFormSet,并且最终在该代码的某处使用了我指定的PizzaForm。但是我不知道如何成功地将信息从PizzaFormSet传递到PizzaForm。
基本上,我愿意就我缺少这个难题的哪一部分提出建议。
问题出在哪里
我已经在forms.py(PizzaForm)中定义了一个表单,该表单需要为Topping获取一个与情境相关的查询集。 view order_pizzas视图确定哪个餐厅将制作和交付比萨饼,并且该餐厅的可用浇头可能与其他餐厅不同。
我不知道如何将这些信息从视图传播到表单,通常情况下,您只是将表单子类化,并添加一些额外的初始化参数即可执行所需的任何操作。
但是在这种情况下,我使用的是表单集而不是单个表单。这意味着我必须找到(或创建)一些渠道以将餐厅信息和/或特定的查询集从视图传递到表单集再传递到表单。我认为这是我的困惑和/或无知的要点。
最佳答案
这是一个解决方案。可能会有更好的选择,但这应该可行。循环浏览表单集中的所有表单,并在choices
字段上更改toppings
变量。像这样:
pizza_form = PizzaFormSet(request.POST or None)
choices = [(t.pk, unicode(t)) for t in restaraunt.toppings.all().order_by('-id')]
for form in pizza_form:
form.fields['toppings'].choices = choices
您也可以覆盖
BaseModelFormset
并覆盖_contruct_forms
方法,将restaraunt对象传递给表单的__init__
,然后在此处更改顶部的选择。但我认为上述解决方案是最快,最简单的。它只是引入了一个额外的循环。