Wiki source for AppengineFormWidgetOverriding


Show raw source

=====Google App Engine: Widget Overriding=====
AppengineForms

==Problem==
By default when you define a model with choices and create a modelform, the widget for that model (the html output) will be a select box. But what if you want the user to be able to select more than one choice. Then you'd want something like a list of checkboxes. The django API offers such a widget. But getting it to function was a bit of a challenge.

==Solution==
In my case, I was trying to figure this out in the context of a wizard I was putting together. (I know djangoforms offer its own wizard framework, but the bundled Google version doesn't support it yet.) So my code a little more complicated, but I've simplified it below.

This is what worked:
%%(python)
# set choice list: notice that we require a tuple of tuples containing both value and label items
# the google examples gave me the impression you could use a 1-D sequence
CHOICES_PICKTWO = (
# value, label
('fast',"fast"),
('cheap',"cheap"),
('works',"works")
)

# our class with the picktwo field using choice list above
class DemoModel(db.Model):
email = db.EmailProperty(required=True)
url = db.LinkProperty(required=True)
picktwo = db.StringProperty(required=True, choices=CHOICES_PICKTWO)
message = db.StringProperty(required=True)
created = db.DateTimeProperty(auto_now_add=True)
modified = db.DateTimeProperty(auto_now=True)


# extending charField with own class that overrides clean method (used for validation) so that
# it requires two items be picked from list
class PickTwoField(forms.CharField):
def clean(self, value):
if len(value) != 2:
raise forms.ValidationError('Please select two (2) choices below')
return value


# modelform class
class DemoModelForm(djangoforms.ModelForm):
"""
NOTE: we have to explicitly pass our choice list as a key argument to our widget constructor
Some examples I saw gave me the impression that you could just set widget to a value
like so: widget=forms.CheckboxSelectMultiple
"""
picktwo = PickTwoField(widget=forms.CheckboxSelectMultiple(choices=CHOICES_PICKTWO))

class Meta:
model = DemoModel
fields = ('email', 'picktwo')


html_form = """
<form method="POST" action="%s">
<table>
%s
</table>
<input type="submit" value="continue" />
</form>
""" % ( action, DemoModelForm() )
%%
Valid XHTML 1.0 TransitionalValid CSSWikkaWiki