如何在Django Select小组件中分组选择? [英] How to group the choices in a Django Select widget?

查看:222
本文介绍了如何在Django Select小组件中分组选择?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在Django选择(下拉菜单)小部件中创建命名选择组,当该小部件在数据模型中自动生成的表单上时?我可以在下面的左侧图片创建小部件吗?

Is it possible to created named choice groups in a Django select (dropdown) widget, when that widget is on a form that is auto-generated from a data Model? Can I create the widget on the left-side picture below?

我在创建一个带有命名组的表单的第一个实验是手动完成 ,如下所示:

My first experiment in creating a form with named groups, was done manually, like this:

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

它工作得很好,在左边创建了带有命名组的下拉菜单。

And it worked nicely, creating the dropdown widget on the left, with named groups.

然后我创建了一个数据模型tha t具有基本相同的结构,并使用Django自动生成模型的形式的能力。它的工作 - 在它显示所有选项的意义上。但是这些选择并不是在命名组中,到目前为止,我还没有想到如何做到这一点 - 甚至是可能的。

I then created a data Model that had basically the same structure, and used Django's ability to auto-generate forms from Models. It worked - in the sense that it showed all of the options. But the options were not in named groups, and so far, I haven't figured out how to do so - if it's even possible.

我发现了几个问题,答案是创建一个表单构造函数并在那里进行任何特殊处理。但是,似乎form.ChoiceField需要一个用于命名组的元组,我不知道如何将一个元组转换成一个QuerySet(这可能是不可能的,如果我将QuerySets正确地理解为指向数据,而不是实际的数据)。

I have found several questions, where the answer was, "create a form constructor and do any special processing there". But It seems like the forms.ChoiceField requires a tuple for named groups, and I’m not sure how to convert a tuple to a QuerySet (which is probably impossible anyway, if I understand QuerySets correctly as being pointer to the data, not the actual data).

我用于数据模型的代码是:

The code I used for the data Model is:

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

如果需要,我会更改数据模型,但这似乎是一个简单的结构。也许太多ForeignKeys?折叠数据并接受非规范化? :)或者有一些方法可以将一个元组转换为一个QuerySet,或者一个可以接受一个ModelChoiceField的东西?

I'll change the data model, if need be, but this seemed like a straightforward structure. Maybe too many ForeignKeys? Collapse the data and accept denormalization? :) Or is there some way to convert a tuple to a QuerySet, or something acceptable to a ModelChoiceField?

更新: / strong>最终代码,基于 meshantz ' answer

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

当然是实际的代码,我会从数据库中获取项目数据。)

(Of course the actual code, I'll have something pull the item data from the database.)

从他连接的djangosnippet的最大变化,似乎是Django已经加入了一些代码,使得可以直接将一个迭代器分配给选项,而不必重写整个类。这是非常好的。

The biggest change from the djangosnippet he linked, appears to be that Django has incorporated some of the code, making it possible to directly assign an Iterator to choices, rather than having to override the entire class. Which is very nice.

推荐答案

快速浏览django.forms.models中的ModelChoiceField代码后,我会说try扩展该类并覆盖其选择属性。

After a quick look at the ModelChoiceField code in django.forms.models, I'd say try extending that class and override its choice property.

设置属性以返回自定义迭代器,基于同一模块中的Orignial ModelChoiceIterator(返回您的元组,重新遇到麻烦) - 一个新的GroupedModelChoiceIterator或一些这样的。

Set up the property to return a custom iterator, based on the orignial ModelChoiceIterator in the same module (which returns the tuple you're having trouble with) - a new GroupedModelChoiceIterator or some such.

我将不得不确定如何写这个迭代器给你,但是我的猜测是,您只需要以自定义的方式返回元组元组,而不是默认设置。

I'm going to have to leave the figuring out of exactly how to write that iterator to you, but my guess is you just need to get it returning a tuple of tuples in a custom manner, instead of the default setup.

很高兴回复评论,因为我很确定这个答案需要一点微调:)

Happy to reply to comments, as I'm pretty sure this answer needs a little fine tuning :)

下面编辑

只是有一个想法,并检查了djangosnippets,结果是有人做的只是这样:
ModelChoiceField与选项组。这是一岁,所以可能需要一些调整来处理最新的django,但正是我在想的。

Just had a thought and checked djangosnippets, turns out someone's done just this: ModelChoiceField with optiongroups. It's a year old, so it might need some tweaks to work with the latest django, but it's exactly what I was thinking.

这篇关于如何在Django Select小组件中分组选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆