web-dev-qa-db-ja.com

Django:ModelMultipleChoiceFieldは最初の選択肢を選択しません

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」、それ以外の場合は変数
 >>> form = Action_Form(initial = {'from_company':[ o.pk for o incontacts_from_company]})#修正で提案されているように
 >>> print form ['from_company'] 
 <ul> 
 </ ul> 
 >>> printcontacts_from_company 
 [<連絡先:テスト担当者>、<連絡先:別の担当者>] 
 
 >>> 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> 

私がそれがうまくいくことを望んでいた方法:
1。私のビューはrequest.GETから「会社」を取得します
2。次に、その「会社」のすべての「連絡先」をフィルタリングします
3。最後に、フォームを作成し、それらの「連絡先」を「initial = {...}」として渡します。

2つの質問:
1。 [まだ回答されていません]ModelMultipleChoiceFieldにこれらの「初期」値を取得させるにはどうすればよいですか?
2。 [回答済み]別の方法として、変数をAction_Form(ModelForm)に渡して、ModelFormで次のようにすることはできますか?

 from_company = forms.ModelMultipleChoiceField(queryset = Contact.objects.filter(company__exact = some_id)#some_idはビューから取得されます
25
dmi

初期値を設定するには、__init__メソッドをAction_Formに追加する必要があります。また、ベースのModelFormクラスで__init__super

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')

詳細については、 DjangoのDynamic ModelForms を参照する別のリンクがあります。

14
Jeff Bauer

1)に返信します

1. ModelMultipleChoiceFieldにこれらの「初期」値を取得させるにはどうすればよいですか?

これは、ModelMultipleChoiceField initial属性を使用して_Action_Form_ ___init___メソッドで実行できます。

def formfield(self, **kwargs)のDjangoソースコード(db/models/fields/related.py))にあるように:

_        # 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()]
_
21
Andre Miras

(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()]
11
Albert Tugushev

前の答えが十分に単純ではなかった場合、私はもう一度1)に答えようとします:

  1. ModelMultipleChoiceFieldにこれらの「初期」値を取得させるにはどうすればよいですか?

Action_Formを元の質問のままにして、これを使用して、必要なものを正確にレンダリングできます。

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