Thanks
Iain
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
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
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()}
@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
>
>
> >
>
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
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
>
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
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
Should the above say RepeatingFieldSet or is there both a
RepeatingFieldSet and a RepeatingFormField widget?
Thanks
Iain
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
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