Django根据ModelForm中的ChoiceField选择填充ManyToMany

时间:2014-04-13 02:06:12

标签: django many-to-many django-queryset

我有一个具有ManyToMany关系的类,我想用它来为应用创建一个控制面板:

class ControlPanel(models.Model):
    viewtype = models.CharField("view type", max_length=32, unique=True)    
    choice1 = models.ManyToManyField(Choice1, null=True)
    choice2 = models.ManyToManyField(Choice2, null=True)
    choice3 = models.ManyToManyField(Choice3, null=True)

其中Choice1Choice2Choice3是我想要呈现为复选框的选项。 controlpanel_choice1controlpanel_choice2controlpanel_choice3是与Choice1Choice2Choice3选项相关的M2M关系表。因此,根据viewtype id,每个Choice*集的选择集可能不同(甚至不存在)。

我从这个ControlPanel类创建了一个表单来生成我的控制面板:

class ControlPanelForm(ModelForm):
    viewtype = forms.ChoiceField(choices = ControlPanel.objects.values_list('id','view'))
    choice1 = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Choice1.objects.all())
    choice2 = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Choice2.objects.all())
    choice3 = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Choice3.objects.all())

    class Meta:
        model = ControlPanel

这会显示3选项*字段。但是,它不会限制对每个viewtype选项的选择,因为我的查询集会为每个.objects.all()字段显示choice*。此外,这将显示对象地址,而不是每个Choice *的名称字段。 我怎样才能做到这一点?我需要为绑定和未绑定表单显示Choice *。我是否需要在构造函数中构建它们,检查我的表单是否有效并获取当前选定的viewtype来构建我的查询集?我可以在ControlPanel类中使用此逻辑,并避免在我的视图函数中编程吗?我会很感激一些例子。

提前致谢。

2 个答案:

答案 0 :(得分:0)

首先,您需要创建一个接受参数的表单

class ControlPanelForm(ModelForm):
    class Meta:
        model = ControlPanel
        widgets = {
            'choice1': forms.CheckboxSelectMultiple(),
            'choice2': forms.CheckboxSelectMultiple(),
            'choice3': forms.CheckboxSelectMultiple(),
        }

    def __init__(self, *args, **kwargs):
        viewtype = kwargs.pop('viewtype')
        super(ControlPanelForm, self).__init__(*args, **kwargs)
        self.fields['choice1'].queryset = Choice1.objects.filter( ... )
        self.fields['choice2'].queryset = Choice2.objects.filter( ... )
        self.fields['choice3'].queryset = Choice3.objects.filter( ... )

正如您所看到的,我已将viewtype作为位置参数传递给表单的init,现在您可以使用它来创建filter()的查询集,而不是使用{{1 }}

此外,使用all()时,无需再次声明表单字段。如果您需要更改任何字段的小部件,使用ModelForm类的widgets选项似乎更合适。

现在,要在您的视图中使用此表单,只需将Meta作为位置参数传递。

viewtype

现在你要做的就是将它放在一个视图中,并在每次传入不同的viewtype = request.POST['viewtype'] form = ControlPanelForm(viewtype=viewtype) 时调用它。

答案 1 :(得分:0)

只是对这个问题的后续跟进:我意识到使用javascript / jQuery在客户端实现这种功能更合乎逻辑。实际上,由于HTM1的非持久性方面,在服务器端具有这样的逻辑是非常尴尬和容易出错的。我在学习基本的jQuery方面遇到了很多麻烦,并且有一种很好的方法可以在浏览器端隐藏/显示选项和结果。