Login

Multiple-Submit-Button Widget for Choice Field

Author:
Archatas
Posted:
August 8, 2008
Language:
Python
Version:
.96
Score:
6 (after 6 ratings)

Django administration provides three buttons for submitting the currently edited object. Each of them has a unique name and depending on the name that is sent to the server, the specific action is performed. I see this as an ugly solution and prefer to have a choice field in the form which would render as submit buttons with different values. Then the values would be checked instead of the names. Therefore, I created the MultipleSubmitButton widget. When <input type="submit" value="Go" /> is used, the value sent to the server always matches the text on the button, but if <button type="submit" value="go">Go</button>, the value and the human representation might differ.

To use the MultipleSubmitButton widget, pass it to the widget parameter of a ChoiceField like this:

SUBMIT_CHOICES = (
    ('save', _("Save")),
    ('save-add', _("Save and Add Another")),
    )

class TestForm(forms.Form):
    do = forms.ChoiceField(
        widget=MultipleSubmitButton,
        choices=SUBMIT_CHOICES,
        )

When you print {{ form.do }} in the template, the following HTML will be rendered:

<ul>
<li><button type="submit" name="do" value="save">Save</button></li>
<li><button type="submit" name="do" value="save-add">Save and Add Another</button></li>
</ul>

When you submit this form and check the validity of it, form.cleaned_data['do'] will return "save" or "save-add" depending on the submit button clicked.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# -*- coding: utf-8 -*-
from django import forms
from django.utils.safestring import mark_safe

class SubmitButton(forms.Widget):
    """
    A widget that handles a submit button.
    """
    def __init__(self, name, value, label, attrs):
        self.name, self.value, self.label = name, value, label
        self.attrs = attrs
        
    def __unicode__(self):
        final_attrs = self.build_attrs(
            self.attrs,
            type="submit",
            name=self.name,
            value=self.value,
            )
        return mark_safe(u'<button%s>%s</button>' % (
            forms.widgets.flatatt(final_attrs),
            self.label,
            ))

class MultipleSubmitButton(forms.Select):
    """
    A widget that handles a list of submit buttons.
    """
    def __init__(self, attrs={}, choices=()):
        self.attrs = attrs
        self.choices = choices

    def __iter__(self):
        for value, label in self.choices:
            yield SubmitButton(self.name, value, label, self.attrs.copy())

    def __unicode__(self):
        return '<button type="submit" />'
        
    def render(self, name, value, attrs=None, choices=()):
        """Outputs a <ul> for this set of submit buttons."""
        self.name = name
        return mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join(
            [u'<li>%s</li>' % force_unicode(w) for w in self],
            ))
    def value_from_datadict(self, data, files, name):
        """
        returns the value of the widget: IE posts inner HTML of the button
        instead of the value.
        """
        value = data.get(name, None)
        if value in dict(self.choices):
            return value
        else:
            inside_out_choices = dict([(v, k) for (k, v) in self.choices])
            if value in inside_out_choices:
                return inside_out_choices[value]
        return None

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 9 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 months ago

Comments

jon_elsas (on September 22, 2010):

amazingly useful drop-in replacement for a single radio-button choice form. thanks!

#

jasonyo (on April 10, 2011):

Excellent. I recommend adding the following import statement:

from django.utils.encoding import force_unicode

#

Please login first before commenting.