Newforms and composite widgets

30 views
Skip to first unread message

Brian Victor

unread,
Dec 9, 2006, 7:14:03 PM12/9/06
to django...@googlegroups.com
One of the things I was hoping for in newforms but haven't found is a
way to do a composite form field that uses multiple <input> elements
that reduce to a single python object. E.g.,

>>> class MyForm(Form):
... postdate = CompositeField(ChoiceField(choices=['Jan', ...]),
... ChoiceField(choices=range(1,32)),
... ChoiceField(choices=range(2000,2010)))
...
>>> str(MyForm())
'<tr><td>Postdate</td><td><select name="postdate1"><option>Jan</option>'
(and so forth, with select fields for all three before closing the td/tr))

If clean() were called on my hypothetical composite field above, it
would return a single datetime object.

Is there a way to obtain this behavior?

--
Brian

Adrian Holovaty

unread,
Dec 10, 2006, 8:18:49 PM12/10/06
to django...@googlegroups.com

Yes, I'm pretty sure this is possible by writing a custom Widget
class. I'll try to implement your example and check it into a new file
django/newforms/extra/widgets.py. Stay tuned...

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Brian Victor

unread,
Dec 17, 2006, 11:32:31 AM12/17/06
to django...@googlegroups.com
Adrian Holovaty wrote:
> On 12/9/06, Brian Victor <homeu...@brianhv.org> wrote:
>> One of the things I was hoping for in newforms but haven't found is a
>> way to do a composite form field that uses multiple <input> elements
>> that reduce to a single python object. E.g.,
[snip]

>> Is there a way to obtain this behavior?
> Yes, I'm pretty sure this is possible by writing a custom Widget
> class. I'll try to implement your example and check it into a new file
> django/newforms/extra/widgets.py. Stay tuned...

I haven't seen that file appear yet. Have you been able to take a look
at this? Should it just be a matter of overriding render and
id_for_label to return the composited widgets?

--
Brian

Adrian Holovaty

unread,
Dec 17, 2006, 2:07:20 PM12/17/06
to django...@googlegroups.com

I haven't had a chance to finish this yet. Yes, it should only be a
matter of overriding render(), id_for_label() and
value_from_datadict().

Adrian Holovaty

unread,
Dec 24, 2006, 3:26:40 PM12/24/06
to django...@googlegroups.com
On 12/9/06, Brian Victor <homeu...@brianhv.org> wrote:
> One of the things I was hoping for in newforms but haven't found is a
> way to do a composite form field that uses multiple <input> elements
> that reduce to a single python object. E.g.,
>
> >>> class MyForm(Form):
> ... postdate = CompositeField(ChoiceField(choices=['Jan', ...]),
> ... ChoiceField(choices=range(1,32)),
> ... ChoiceField(choices=range(2000,2010)))
> ...
> >>> str(MyForm())
> '<tr><td>Postdate</td><td><select name="postdate1"><option>Jan</option>'
> (and so forth, with select fields for all three before closing the td/tr))

Merry Christmas! In changeset [4236], I've implemented this as
django.newforms.extras.SelectDateWidget. See the new unit tests for
example usage:

http://code.djangoproject.com/changeset/4236

I still need to add unit tests that demonstrate how the value is split
into three HTML fields but combined into a single datetime.date object
by the widget value_from_datadict() method.

gordyt

unread,
Jan 3, 2007, 10:07:19 AM1/3/07
to Django users
Adrian I have been experimenting with the SelectDateWidget and I have
noticed one bit of strange behavior. Wondering if I'm using it
incorrectly.

My original element in the form class is this:

date_opened = forms.DateField(initial=date.today())

This works as expected and if the data supplied when the form is
initialized provides a date value for date_opened, it uses the supplied
value. If it does not, it uses today's date. Note that it is a
required field.

Now, if I use this instead:

date_opened = forms.DateField(
initial=date.today(),widget=SelectDateWidget)

This does render the composite widget just fine, but it will not use a
date_opened value that is supplied with the form class is instantiated
and so displays the error saying that a required field is missing.

Any thoughts?

Thanks!

--gordon

Adrian Holovaty

unread,
Jan 3, 2007, 12:31:07 PM1/3/07
to django...@googlegroups.com
On 1/3/07, gordyt <gor...@gmail.com> wrote:
> date_opened = forms.DateField(
> initial=date.today(),widget=SelectDateWidget)
>
> This does render the composite widget just fine, but it will not use a
> date_opened value that is supplied with the form class is instantiated
> and so displays the error saying that a required field is missing.

When you pass the data to the Form constructor, you'll have to pass
three separate values -- 'date_opened_month', 'date_opened_day' and
'date_opened_year' -- rather than one value 'date_opened'. This is
necessary because the SelectDateWidget requires three values instead
of one. Make sense?

Reply all
Reply to author
Forward
0 new messages