Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use two different Django Form at the same template?

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?

like image 996
Amit Pal Avatar asked Jun 29 '12 20:06

Amit Pal


People also ask

Can HTML form have two forms in one?

If two or more forms on the same page use the same IDs then the connector hooks into the first form on the DOM. This is because Javascript assumes unique element IDs per HTML standards.

How many types of Django forms are there?

In this case, our form has four fields: subject , message , sender and cc_myself . CharField , EmailField and BooleanField are just three of the available field types; a full list can be found in Form fields.


2 Answers

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.

like image 182
Alasdair Avatar answered Sep 20 '22 01:09

Alasdair


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_".

like image 24
Sergey Golovchenko Avatar answered Sep 23 '22 01:09

Sergey Golovchenko