dynamically adding widget fields at runtime?

0 views
Skip to first unread message

iain duncan

unread,
Jun 20, 2007, 9:17:01 PM6/20/07
to turbogears
Wondering if there is a smart way to add fields to a form widget based
on runtime factors ( ie a db hit ) or whether this is just asking for
trouble with form encode. Anyone do this? And if so, how do you handle
validation?

Thanks
Iain

Diez B. Roggisch

unread,
Jun 21, 2007, 2:50:31 AM6/21/07
to turbo...@googlegroups.com
iain duncan schrieb:

Depending on your situation, you can do this:

class FeatureSchema(validators.Schema):
selected_quantity = validators.Int(not_empty=True)
chosen = validators.Int(not_emtpy=True)
comment = validators.FancyValidator()

class OccupancySchema(validators.Schema):
start_time = varms_validators.Duration(not_empty=True)
end_time = varms_validators.Duration(not_empty=True)
features = formencode.ForEach(FeatureSchema())

That will make features an arbitrary number of FeatureSchema-values.

Diez

iain duncan

unread,
Jun 21, 2007, 3:12:39 AM6/21/07
to turbo...@googlegroups.com

Thanks Diez ( again! ). What I would really like to do is make the
number of some certain fields vary with a dynamic value from the db. I'm
not clear from the above whether that is possible. Does the example
above mean that the number of feature schema validated is just
determined by the number of incoming variables to formencode?

Thanks
Iain


Walter...@gmail.com

unread,
Jun 21, 2007, 5:19:45 AM6/21/07
to TurboGears

Hi,
this is just a beginner's attempt, but it could be useful (if I have
understood what you have in mind). Assume you have a list called
visibleTables that contains all the tables you want to make user-
visible through this controller.

def list(self, what="Subject"):
"""Display any table from the database"""
if (what in visibleTables):
what = ""+what
currentSQLTable= eval(what) ## I know, it is horrible, I am in a
hurry, don't do this at home

#The names of the columns, gotten from the DB at runtime
fieldNames = currentSQLTable.sqlmeta.columns.keys()

#An array of anonymous functions that access named properties of
query results
fieldAccessors = [lambda x,n=n: getattr(x,n) for n in fieldNames]

#As required by the DataGrid widget
fields = zip(fieldNames,fieldAccessors)

#Get actual data from the database
data= currentSQLTable.select()

if (data.count()==0):
#empy table? display error
WidgetToShow=widgets.Label(field_class="trailmapsError",
default="This table is empty.")
else:
#convert iterable result from select into list
data=list(data)
WidgetToShow=widgets.DataGrid(fields=fields,default=data)
else:
#That table cannot be shown
WidgetToShow=widgets.Label(default="We are not able to display a
table called '"+what+"', sorry. Check the model.")

return dict(what=what,data=WidgetToShow)

and then the template is something really trivial like this

<h1>${what}</h1>
${data.display()}


remi jolin

unread,
Jun 21, 2007, 5:39:48 AM6/21/07
to turbo...@googlegroups.com
Hello,
I did something similar where the form is built during the request to
the page :
something like (just consider the spirit...)

@expose(...)
def mypage(self, id, **kw):
# setup your fields list
fields = []
for f in Fields.select(id):
if f.is_type=='checkbox':
fields.append(CheckboxWidget(f.name)
else:
fields.append(TextField(f.name, validator=UnicodeTextString())

# define your form
form = TableForm(fields=fields)

if kw:
# the user has filed the form, we need to validate it
@validate(form=form)
def get_errors(self, tg_errors=None, **kw)
return tg_errors, kw

# do the actual validation
tg_errors, kw = get_errors(self, **kw)
if not tg_errors:
# no validation error : save whatever you want to save

# go to the next page...
raise redirect('next page')

# first call to the page or validation error
return dict(form=form,
value=kw)


> Thanks
> Iain
>
>
> >
>

iain duncan

unread,
Jun 21, 2007, 2:45:29 PM6/21/07
to turbo...@googlegroups.com

Thanks Remi! That should ge me something to play with. A couple of
further questions. What happens with @validate if the form has extra
fields not in its validation schema? Could I still use a static form
widget and append extra fields dynamically if they don't need validation
or I'm willing to do it manually?

Thanks
Iain


remi jolin

unread,
Jun 21, 2007, 2:58:37 PM6/21/07
to turbo...@googlegroups.com
In my solution, the form you validate IS the form displayed as you
entirely define it within the method (same method displays the form and
is the target of the <form> tag...), so there is no fields unknown to
@validate. Of course, it also makes the assumption that the fields in
the form are the same for a given "id" whenever you call the method.

Could you explain what you are thinking about ? I'm not sure it is easy
to add extra fields to an existing static form. What would append if 2
people request that form at the same time with different fields to be
displayed ?? We are in a multi-threaded environment...
> Thanks
> Iain
>

Diez B. Roggisch

unread,
Jun 21, 2007, 7:05:47 PM6/21/07
to turbo...@googlegroups.com
iain duncan schrieb:

It is dependend from the numbers of incoming variables, as they have to
be named in the proper way.

For the case at hand that means that features are given like this

features-1.selected_quantity
features-2.selected_quantity

Obviously you have to render the form fields accordingly. Unfortunately
I'm not sure right now how that happens exactly, because the code above
is validating some JS-generated forms. But AFAIK using e.g. fieldset
with feature-widgets and passing an proper array of dicts to them should
render the form correctly.

Diez

Chris Miles

unread,
Jun 22, 2007, 3:52:06 AM6/22/07
to turbo...@googlegroups.com, Chris Miles

On 21 Jun 2007, at 08:12, iain duncan wrote:
> Thanks Diez ( again! ). What I would really like to do is make the
> number of some certain fields vary with a dynamic value from the
> db. I'm
> not clear from the above whether that is possible. Does the example
> above mean that the number of feature schema validated is just
> determined by the number of incoming variables to formencode?
>

Is the RepeatingFormField widget what you are looking for? You
specify the repetition count at run-time and it renders its contained
form widgets that many times. Validation is handled properly too.

Cheers
CM

iain duncan

unread,
Jun 27, 2007, 11:14:18 PM6/27/07
to turbo...@googlegroups.com

Should the above say RepeatingFieldSet or is there both a
RepeatingFieldSet and a RepeatingFormField widget?

Thanks
Iain


iain duncan

unread,
Jun 27, 2007, 11:58:06 PM6/27/07
to turbo...@googlegroups.com
> >
> > Thanks Remi! That should ge me something to play with. A couple of
> > further questions. What happens with @validate if the form has extra
> > fields not in its validation schema? Could I still use a static form
> > widget and append extra fields dynamically if they don't need validation
> > or I'm willing to do it manually?
> >
> >
> In my solution, the form you validate IS the form displayed as you
> entirely define it within the method (same method displays the form and
> is the target of the <form> tag...), so there is no fields unknown to
> @validate. Of course, it also makes the assumption that the fields in
> the form are the same for a given "id" whenever you call the method.
>
> Could you explain what you are thinking about ? I'm not sure it is easy
> to add extra fields to an existing static form. What would append if 2
> people request that form at the same time with different fields to be
> displayed ?? We are in a multi-threaded environment...

What I'm hoping is that I can put the callable part of dynamically
adding fields away in my widget module, so that when I pass the fields
into the widget at runtime, a dynamic value from the db will repeat some
parts.

So say in my widget module I have something like

class PageEditFields( object ):
... field defs here ...

And those widget fields go into the widget when in the controller I do:

page_edit_form = PageWidget( fields=PageEditFields() )

Is there a nice way to make the PageEditField class itself do the
appending of extra fields when it is called? Sort of like how you can
pass a callable to options for a widget? Do I just need to make the
PageEditFields class be a callable that returns a list of widgets?

Hmm, it's hard to even explain my confusion. Sorry if it is not making
sense!

Thanks again!
Iain


iain duncan

unread,
Jun 28, 2007, 1:15:58 AM6/28/07
to turbo...@googlegroups.com

I have one more question about the above. If I want to break up the
processing of a form with the generation of it into two different
methods, how would I make sure that tg_errors gets to the other method
after I a redirect? I tried splitting up the above into my_page and
_update_mypage, but I lose the tg_errors.

Thanks
Iain

Reply all
Reply to author
Forward
0 new messages