Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a radio button across forms in a formset in django

I have a page, where I display different forms using formsets.

These are my models:

class Phone(models.Model):
    mac = models.CharField()

class PhoneLine(models.Model):
    phone = models.ForeignKey(Phone)
    voicemail = models.BooleanField("Voice Mail", default=False)

A phone can have many lines (phoneline), but only one phone line can have voice mail enabled.

By default when I display phonelines using formset, the voice mail field displays as a check box as follows.(I have added prefix to the formset, based on requirements)

form1 of the formset
<input type="checkbox" name="phone_client_line_1-0-voicemail" id="id_phone_client_line_1-0-voicemail">

form2 of the formset
<input type="checkbox" name="phone_client_line_1-1-voicemail" id="id_phone_client_line_1-1-voicemail">

(The checking and un-checking of the checkboxes update the backend)

Based on this thread, Django - Show BooleanField in a formset as one group of radio buttons, I modified the init and add_prefix method of my phoneline form to now display the voicemail field as radio buttons..

class PhoneLineForm(ModelForm):

def __init__ (self, *args, **kwargs):
    super(PhoneLineForm, self).__init__(*args, **kwargs)
    self.fields['voicemail'] = BooleanField( widget = RadioSelect(choices=((self.prefix+"-"+str("voicemail"), 'Voicemail LIne'),)))

def add_prefix(self, field):
    if field == 'voicemail': return ('%s_%s') %(field, self.instance.phone.id)
    else: return self.prefix and ('%s-%s' % (self.prefix, field)) or field

This modifies the html output to the following:

form1 of the formset
<input type="radio" id="id_voicemail_1_0" value="phone_client_line_1-0-voicemail" name="voicemail_1">

form2 of the formset
<input type="radio" id="id_voicemail_1_0" value="phone_client_line_1-1-voicemail" name="voicemail_1">

As you see, now for the radio field voicemail_1, I have the value of the selected phoneline. If I submit this form, after I select a voicemail_1 radio, it does not update the database.

How can I capture the value of the phoneline selected on submit?. If I overwrite the save method of the phonelineform, what should it contatin..?

Any pointers on this would be appreciated. Thanks!!

like image 979
akotian Avatar asked Nov 04 '22 18:11

akotian


1 Answers

I'd actually suggest simplifying this, and relying on JavaScript (you can always validate server-side and show a message to the user if they have selected more than one phone line with voicemail because they've not got JavaScript enabled).

This would be simpler than trying to hack the field names and values. Django formsets are hard enough beasts to wrangle at the best of times, so adding further server-side complexity is often not worth the hassle, especially when the problem can be solved - in a not too-inelegant way - via a little judicious jQuery work.

$('input[name^="voicemail_"]').on('click',
    function() {
        $('input[name^="voicemail_"]').not($(this)).prop('checked', false);
    }
);

Just a rough-and-ready suggestion; hope it's useful.

like image 131
Steadman Avatar answered Nov 15 '22 05:11

Steadman