在 Django 中,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>
我希望它能发挥作用的方式是:
- 我的视图从
request.GET
中获取“company”。 - 然后,它过滤该“company”的所有“contacts”。
- 最后,它创建一个表单并将这些“contacts”作为“initial={…}" 传递。
我有两个问题:
- 如何让
ModelMultipleChoiceField
接受这些“initial”值? - 作为替代方案,我能否将变量传递给
Action_Form(ModelForm)
,以便在我的ModelForm
中可以拥有:
from_company = forms.ModelMultipleChoiceField(queryset=Contact.objects.filter(company__exact=some_id) # where some_id comes from a view
解决方案
回答 1:
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()]
回答 2:
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')
回答 3:
>>> form4 = Action_Form(initial={'from_company': Contact.objects.all().values_list('id',flat=True)})
>>> print form4['from_company']
回答 4:
class Action_Form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(Action_Form, self).__init__(*args, **kwargs)
self.initial['from_company'] = [c.pk for c in Contact.object.filter()]