在Django自动生成的表单中,是否可以创建具有命名分组选择的下拉框?我能否创建左侧图片中的小部件?
我第一次尝试创建具有命名分组的表单是手动完成的,就像这样:
class GroupMenuOrderForm(forms.Form):
food_list = [(1, 'burger'), (2, 'pizza'), (3, 'taco'),]
drink_list = [(4, 'coke'), (5, 'pepsi'), (6, 'root beer'),]
item_list = ( ('food', tuple(food_list)), ('drinks', tuple(drink_list)),)
itemsField = forms.ChoiceField(choices = tuple(item_list))
def GroupMenuOrder(request):
theForm = GroupMenuOrderForm()
return render_to_response(menu_template, {'form': theForm,})
# generates the widget in left-side picture
它很好地起作用了,在左侧创建了下拉小部件,其中包含命名分组。
然后我创建了一个数据模型,它基本上具有相同的结构,并利用了Django从模型自动生成表单的能力。 它可以工作-在显示所有选项方面是可以的。 但是选项不在命名分组中,到目前为止,我还没有找到如何实现这一点-如果可能的话。
我发现了几个问题的答案是“创建一个表单构造函数并在那里进行任何特殊的处理”。 但似乎forms.ChoiceField需要一个元组来进行命名分组,并且我不确定如何将元组转换为QuerySet(如果我正确理解QuerySet是指向数据而不是实际数据,那么这可能是不可能的)。
我用于数据模型的代码是:
class ItemDesc(models.Model):
''' one of "food", "drink", where ID of “food” = 1, “drink” = 2 '''
desc = models.CharField(max_length=10, unique=True)
def __unicode__(self):
return self.desc
class MenuItem(models.Model):
''' one of ("burger", 1), ("pizza", 1), ("taco", 1),
("coke", 2), ("pepsi", 2), ("root beer", 2) '''
name = models.CharField(max_length=50, unique=True)
itemDesc = models.ForeignKey(ItemDesc)
def __unicode__(self):
return self.name
class PatronOrder(models.Model):
itemWanted = models.ForeignKey(MenuItem)
class ListMenuOrderForm(forms.ModelForm):
class Meta:
model = PatronOrder
def ListMenuOrder(request):
theForm = ListMenuOrderForm()
return render_to_response(menu_template, {'form': theForm,})
# generates the widget in right-side picture
如果必要的话,我会更改数据模型,但这似乎是一个简单明了的结构。也许外键太多了?折叠数据并接受非规范化? :) 或者有没有一种方法将元组转换为QuerySet,或者任何可以被ModelChoiceField接受的东西?
class FooIterator(forms.models.ModelChoiceIterator):
def __init__(self, *args, **kwargs):
super(forms.models.ModelChoiceIterator, self).__init__(*args, **kwargs)
def __iter__(self):
yield ('food', [(1L, u'burger'), (2L, u'pizza')])
yield ('drinks', [(3L, u'coke'), (4L, u'pepsi')])
class ListMenuOrderForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ListMenuOrderForm, self).__init__(*args, **kwargs)
self.fields['itemWanted'].choices = FooIterator()
class Meta:
model = PatronOrder
(当然,实际代码中,我会让某个东西从 数据库 中提取项目数据。)
与他提供的 djangosnippet 相比,最大的改变似乎是 Django 已经整合了一些代码,使得可以直接将一个迭代器赋值给 choices,而不必覆盖整个类。这非常好。