6

My forms.py:

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

AlertCountFormset = modelformset_factory(Alert,
                                       form = AlertForm)

Another Django Form class:

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)

Below is for the choice fields:

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

I want to fill these two forms at the same template. So i choose to write same views for both i.e. :

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)

According to that in my 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>

Everything is right, It is saving the data to database also. But the problem is whenever i filled the aler_form and click on the update buttone. it also update the another form with the same value or vice versa. For example if i choose

1 2 3 for high , medium and low for alert_Form

Then it also save the same value for notify_form. Why is this happening. Is that something wrong with the views?

Amit Pal
  • 10,604
  • 26
  • 80
  • 160

2 Answers2

14

Use the prefix argument so that your field names don't clash.

For example:

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

You need to use the same prefix in your unbound forms.

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

The advantage of using prefix is that you don't need to manually rename the fields, as umnik700 suggests in their answer.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
3

The problem is that on your forms the fields have the same names.

request.POST is a dictionary-like object. So it only contains the name/value pairs from the request. If the field names are the same on both of the forms then when you call

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

they are initialized with the same values. To resolve this make the names to be unique between your two forms. For example prefix all the field names on the AlertForm with "alert_".

Sergey Golovchenko
  • 18,203
  • 15
  • 55
  • 72
  • Sorry i didn't got you. Which two names? – Amit Pal Jun 29 '12 at 20:50
  • Thanks for the answering :) One more thing. Is this possible in Django-Form, whenever i am going to update my all fields in the forms. All of the fields should shows the previous saved value in database. – Amit Pal Jun 29 '12 at 20:54
  • 1
    Yes, it is possible. The extra_context that contain two form instances. They way you do it right now is you pass uninitialized forms. If you want to display the data you need to initalize them. – Sergey Golovchenko Jun 29 '12 at 21:00