How to create a form with dynamic number of fields?

850 views
Skip to first unread message

Low Kian Seong

unread,
Nov 16, 2008, 12:14:16 AM11/16/08
to django...@googlegroups.com
Dear all,

Could anyone here please let me know of the logic or example of doing
a form with dynamic number of fields (ie. a field with a 'Add more
field' button). I know how to do it using javascript. However it's the
logic behind that gets me. Suggestions?

--
Low Kian Seong
blog: http://lowkster.blogspot.com

Ryan Witt

unread,
Nov 16, 2008, 5:01:30 AM11/16/08
to Django users
I've recently had a situation where I needed to create dynamic forms
and corresponding code to handle them.

One thing that you should know about python is that there's nothing
special about classes, you can take a collection of attributes and
methods and use them to create a new class on-the-fly using python's
type() function. You can use this to dynamically build a form class
with a new field.

My roommate wrote a great blog post on how to do build classes
dynamically (http://askawizard.blogspot.com/2008/09/metaclasses-python-
saga-part-4_30.html), which you should read before attempting this.

Once you understand what that is talking about (or not), you end up
writing some code like this:

If you want this form to be dynamic:

class MyDynamicForm(Form):
foo = CharField(max_len = 100)
bar = IntegerField()
def clean_foo(self):
value = self.cleaned_data['foo']
if value != 'foo':
raise ValidationError('foo is not foo!')
def clean_bar(self):
value = self.cleaned_data['bar']
if value != 42:
raise ValidationError('wrong answer')

You could build it programatically with:

# Our base classes (which you could build programatically if you
wanted)
bases = (Form,)

# Our class attributes
attys = {
'foo' : CharField(max_len = 100),
'bar' : IntegerField(),
}

# This returns a clean method built from some parameters
def general_clean(name, correct_value, error_text):
def inner(self):
value = self.cleaned_data[name]
if value != correct_value:
raise ValidationError(error_text)
return inner

# Now add the clean methods. You could just define methods and assign,
but this illustrates generating them programatically.
for name, correct_value, error_text in (
('foo', 'foo', 'foo is not foo!'),
('bar', 42, 'wrong answer'),
):
attys['clean_' + name] = general_clean(name, correct_value,
error_text)

# Now, to create the dynamic class, you need the following
incantation:
DynamicForm = getattr(Form, '__metaclass__', type)('DynamicForm',
bases, attys)

# That only creates the *class*, we still have to create an instance
form = DynamicForm({'foo': 'foo', 'bar': 42})

Does this help? It would let you dynamically add elements and handlers
to the form that django is aware of, thus you get all the benefits of
using the form framework. Let me know if this is a bit thick and I'll
be happy to explain it and perhaps blog a more coherent example.

--Ryan


Ryan Witt

unread,
Nov 16, 2008, 5:00:23 AM11/16/08
to Django users

Low Kian Seong

unread,
Nov 16, 2008, 6:55:06 AM11/16/08
to django...@googlegroups.com
Thanks Ryan for the reply. Another idea that came to me is .... can we
make an input like a list?
as in <input type="text" name=alotofinput[] ...

all the text inputs will have a similar name then iterate over them
using POST and then pump the data into the database?

Will something like that work?

Ronny Haryanto

unread,
Nov 18, 2008, 1:07:36 PM11/18/08
to django...@googlegroups.com
On Sun, Nov 16, 2008 at 12:14 PM, Low Kian Seong <djang...@gmail.com> wrote:
> Could anyone here please let me know of the logic or example of doing
> a form with dynamic number of fields (ie. a field with a 'Add more
> field' button). I know how to do it using javascript. However it's the
> logic behind that gets me. Suggestions?

James Bennett just recently wrote a (excellent) blog post about dynamic forms:
http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/

Ronny

Reply all
Reply to author
Forward
0 new messages