我无法使用正确的代码,但我发现了披萨/浇头问题并且它已经关闭了,所以我要修改它来提问我的问题。 Django ModelForm for Many-to-Many fields
我们有Pizza和Topping很棒。让我们说我们经营一系列商店而不是所有商店都有所有成分。这意味着我们需要一个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)
forms.py
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,但是我被卡住了。
基本上我可以告诉我,我需要以某种方式将信息从视图传播到formset到表单,以便可以正确初始化表单上的查询集。我只是无法弄清楚如何做到这一点。
所以这是我找到答案的最接近的答案,但我似乎无法弄清楚如何确保这项工作: Django filter ModelFormSet field choices... different from limiting the Formset's queryset
关键在于,我并没有试图要求某人发布完全解决我问题的10行代码,而是说明了我的知识缺乏的地方。我知道我生成了一个PizzaFormSet,并最终在该代码的内部某处使用我指定的PizzaForm。但我不知道如何成功地将信息从PizzaFormSet传递到PizzaForm。
基本上,我愿意放弃一笔赏金,以获得关于我错过这个难题的哪一部分的建议。
我在forms.py(PizzaForm)中定义了一个表单,它需要为Topping获取一个依赖于情境的查询集。视图order_pizzas决定了哪家餐厅将制作和提供比萨饼,该餐厅的配料可能与其他餐厅不同。
我不知道如何将这些信息从视图传播到表单,通常你只是将表单子类化并添加一些额外的init kwargs来做你想做的事。
但在这种情况下,我使用的是formset而不是单一的形式。这意味着我必须找到(或制作)一些频道将餐馆信息和/或特定查询集从视图传递到表单到表单。我认为这是我的主要困惑和/或无知。
答案 0 :(得分:3)
这是一个解决方案。可能有一个更好的,但这应该工作。遍历表单集中的所有表单,并更改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__
,然后在那里更改顶部的选择。但我认为上述解决方案是最快捷,最简单的。它只是引入了一个额外的循环。
答案 1 :(得分:1)
您可以拥有一家制作PizzaForms的工厂:
def pizzaform_factory(restaurant):
class PizzaForm(ModelForm):
class Meta:
model = Pizza
toppings = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple(),
queryset=restaurant.toppings.all()
)
return PizzaForm
并在您的视图中使用它:
PizzaForm = pizzaform_factory(restaurant)
PizzaFormSet = modelformset_factory(Pizza, form=PizzaForm, extra=1)
或许对您的模型进行约束以确保您无法创建不可能的订单会很好。如果您不使用pizzaform_factory
(即使用管理员,shell脚本或API调用),您仍然可以获得无法填充的订单。