Django:ModelMultipleChoiceField不选择初始选择

时间:2009-01-28 15:30:03

标签: python django django-models django-forms

ModelMultipleChoiceField没有选择初始选择,我无法在我的示例中进行以下修复(链接如下):

http://code.djangoproject.com/ticket/5247#comment:6

我的模特和表格:

class Company(models.Model):
    company_name = models.CharField(max_length=200)

class Contact(models.Model):
    company = models.ForeignKey(Company)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

class Action(models.Model):
    company = models.ForeignKey(Company, blank=True, null=True)
    from_company = models.ManyToManyField(Contact, verbose_name='Participant(s) from "Company"', blank=True, null=True)

class Action_Form(ModelForm):
    from_company = forms.ModelMultipleChoiceField(queryset=Contact.objects.none(), widget=forms.CheckboxSelectMultiple())
    class Meta:
        model = Action

我的所作所为和结果:

>>> contacts_from_company = Contact.objects.filter(company__exact=1) # "1" for test, otherwise a variable
>>> form = Action_Form(initial={'from_company': [o.pk for o in contacts_from_company]}) # as suggested in the fix
>>> print form['from_company']
<ul>
</ul>
>>> print contacts_from_company
[<Contact: test person>, <Contact: another person>]

>>> form2 = Action_Form(initial={'from_company': contacts_from_company})
>>> print form2['from_company']
<ul>
</ul>

>>> form3 = Action_Form(initial={'from_company': Contact.objects.all()})
>>> print form3['from_company']
<ul>
</ul>

我希望它能起作用的方式:
我的观点得到了“公司”的请求.GET
2.然后它过滤所有“公司”的“联系人” 3.最后,它创建一个表单并将这些“联系人”传递为“initial = {...}”

两个问题:
1。 [尚未回答] 如何让ModelMultipleChoiceField获取那些“初始”值?
2。 [回答] 作为替代方案,我可以将变量传递给Action_Form(ModelForm),以便在我的ModelForm中可以有:

from_company = forms.ModelMultipleChoiceField(queryset=Contact.objects.filter(company__exact=some_id) # where some_id comes from a view

4 个答案:

答案 0 :(得分:21)

我正在回复1)

1。如何让ModelMultipleChoiceField获取那些“初始”值?

可以使用ModelMultipleChoiceField Action_Form属性在__init__ initial方法中完成此操作。

正如它在Django源代码中所说的那样( db / models / fields / related.py ) 在def formfield(self, **kwargs)

        # If initial is passed in, it's a list of related objects, but the
        # MultipleChoiceField takes a list of IDs.

所以你需要给它一个ID列表:

class Action_Form(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(Action_Form, self).__init__(*args, **kwargs)
        self.fields['from_company'].initial = [c.pk for c in Contact.object.filter()]

答案 1 :(得分:14)

您需要向__init__添加Action_Form方法以设置初始值,并记住通过 super <在基础__init__课程上调用ModelForm /强>

class Action_Form(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(Action_Form, self).__init__(*args, **kwargs)
        self.fields['from_company'].queryset = Contact.object.filter(...

如果您计划将过滤器参数作为关键字参数传递给Action_Form,则需要在调用super之前将其删除:

myfilter = kwargs['myfilter']
del kwargs['myfilter']

或者,可能更好:

myfilter = kwargs.pop('myfilter')

有关详细信息,请参阅Dynamic ModelForms in Django的另一个链接。

答案 2 :(得分:11)

如果以前的答案不够直截了当,我会再次尝试回答1):

  
      
  1. 如何让ModelMultipleChoiceField获取那些“初始”值?
  2.   

您可以保留原始问题中的Action_Form,并使用它来准确呈现您想要的内容:

>>> form4 = Action_Form(initial={'from_company': Contact.objects.all().values_list('id',flat=True)})
>>> print form4['from_company']

答案 3 :(得分:10)

回答(1)问题!

这不起作用:

self.fields['from_company'].initial = [c.pk for c in Contact.object.filter()]

确实有效

self.initial['from_company'] = [c.pk for c in Contact.object.filter()]