5

マイforms.py:2つの異なるDjangoフォームを同じテンプレートで使用するには?

class AlertForm(forms.ModelForm): 
class Meta: 
    model=Alert 
    fields = ('high','medium', 'user') 
    widgets = { 
     'user': forms.HiddenInput() 
    } 

AlertCountFormset = modelformset_factory(Alert, 
             form = AlertForm) 

別のDjangoのFormクラス:私は同じで、これら二つのフォームを記入したい

NOTIFIER_TYPE = (
(0, _('E-mail')), 
(1, _('Skype')), 
(2, _('IRC')) 
) 

:以下

class NotifierForm(forms.ModelForm): 
high = forms.ChoiceField(choices=NOTIFIER_TYPE) 
medium = forms.ChoiceField(choices=NOTIFIER_TYPE) 
low = forms.ChoiceField(choices=NOTIFIER_TYPE) 

def save(self, commit=True): 
    alert = super(NotifierForm, self).save(commit=False) 
    alert.high = self.cleaned_data["high"] 
    alert.medium = self.cleaned_data["medium"] 
    alert.low = self.cleaned_data["low"] 
    alert.save() 
    return alert 

class Meta: 
    model=Notifier 
    fields = ('high','medium', 'low', 'user') 
    widgets = { 
     'user': forms.HiddenInput() 
    } 

NotifierFormset = modelformset_factory(Notifier, 
            form = NotifierForm) 

選択フィールドにありますテンプレート。だから私は両方、すなわちのために同じビューを書くことを選択します。

def profile_setting(request, slug): 
if request.method == 'POST': 
    alert_form = AlertForm(request.POST) 
    notifier_form = NotifierForm(request.POST) 
    if alert_form.is_valid() and notifier_form.is_valid(): 
     alert = alert_form.save(commit=False) 
     notifier = notifier_form.save(commit=False) 
     alert.user = request.user.username 
     notifier.user = request.user.username 
     notifier.save() 
     alert.save() 
     return HttpResponseRedirect(reverse('profile_setting', args=[slug])) 

extra_context = { 
    'alert_form': AlertForm(), 
    'notifier_form': NotifierForm() 
} 
return direct_to_template(request,'users/user_profile_setting.html', 
          extra_context) 

私template.htmlのそれによると:

{% block content %} 
<h3>{% trans "Alerts limit" %}</h3> 
<form action="" method="POST">{% csrf_token %} 
    {{ alert_form.as_p }} 
    <input type="submit" value="{% trans 'Update' %}" /> 
</form> 

<h3>{% trans "Notifier setting" %}</h3> 
<form action="" method="POST">{% csrf_token %} 
    {{ notifier_form.as_p }} 
    <input type="submit" value="{% trans 'Update' %}" /> 
</form> 

すべてが右である、それはまた、データベースにデータを保存しています。しかし、問題は、私がaler_formに記入し、更新ボタンをクリックするたびにです。別のフォームを同じ値で更新するか、またはその逆でも更新します。たとえば、私が選択した場合

1 2 3 for high , medium and low for alert_Form 

次に、notify_formに同じ値を保存します。なぜこうなった。それはビューに間違っていますか?

答えて

12

フィールド名が衝突しないように、引数はprefixです。

例えば:

alert form = AlertForm(request.POST, prefix='alert') 
notifier_form = NotifierForm(request.POST, prefix='notifier') 

あなたが結合していないフォームで同じプレフィックスを使用する必要があります。

extra_context = { 'alert_form': AlertForm(prefix='alert'), notifier_form': NotifierForm(prefix='notifier') } 

接頭辞を使用することの利点は、umnik700が自分の答えに示唆するようあなたは、手動でフィールドの名前を変更する必要がないことです。

+0

その変更は別として。テンプレート側に変更を加える必要がありますか? –

+0

いいえ、テンプレートを変更する必要はありません。 – Alasdair

+0

追加した後。何も起こっていない。つまり、データベースに値することはありません。エラーがなくても –

3

フォームには同じ名前のフィールドがあるという問題があります。

request.POSTは辞書のようなオブジェクトです。したがって、リクエストに含まれる名前と値のペアのみが含まれます。両方のフォームでフィールド名が同じである場合は、

alert_form = AlertForm(request.POST) 
notifier_form = NotifierForm(request.POST) 

これらは同じ値で初期化されます。これを解決するには、2つのフォーム間で名前を一意にする必要があります。たとえば、AlertFormのすべてのフィールド名に "alert_"を付けるとします。

+0

申し訳ありませんが、私はあなたを得ていません。どちらの名前ですか? –

+0

応答ありがとう:) もう一つ。フォームのすべてのフィールドを更新するときはいつでも、これはDjango-Formで可能ですか?すべてのフィールドには、以前に保存された値がデータベースに表示されます。 –

+1

はい、可能です。 2つのフォームインスタンスを含むextra_context。あなたが今それを行う方法は、初期化されていないフォームを渡すことです。データを表示する場合は、それらを初期化する必要があります。 –

関連する問題