And, more or less, with some slight differences in spellings, and one additional feature this is what is now in Colander 0.8:
http://docs.repoze.org/colander/binding.html - C On Wed, 2010-09-08 at 12:25 -0400, Chris McDonough wrote: > I've been thinking about how to solve this problem, and what I've come > up with so far is this: > > - Schemas may be bound to a set of values. When a schema is bound, > it is cloned, and any "deferred" values it has will be resolved. > > - A deferred value is a callable that accepts the schema node being > bound and a set of arbitrary keyword arguments. It should > return a value appropriate for its usage (a widget, a missing value, > a validator, etc). > > - Deferred values are not resolved until the schema is bound. > > - Schemas are bound via "SomeSchema().bind(**kw)". The values in "kw" > are passed to each deferred value along with the schema node being > bound. > > Here's an example: > > """ > @colander.deferred > def deferred_date_validator(node, **kw): > max_date = kw.get('max_date') > if max_date is None: > max_date = datetime.date.today() > return colander.Range(min=datetime.date.min, max=max_date) > > @colander.deferred > def deferred_date_description(node, **kw): > max_date = kw.get('max_date') > if max_date is None: > max_date = datetime.date.today() > return 'Blog post date (no earlier than %s)' % max_date.ctime() > > @colander.deferred > def deferred_date_missing(node, **kw): > default_date = kw.get('default_date') > if default_date is None: > default_date = datetime.date.today() > return default_date > > @colander.deferred > def deferred_body_validator(node, **kw): > max_bodylen = kw.get('max_bodylen') > if max_bodylen is None: > max_bodylen = 1 << 18 > return colander.Length(max=max_bodylen) > > @colander.deferred > def deferred_body_description(node, **kw): > max_bodylen = kw.get('max_bodylen') > if max_bodylen is None: > max_bodylen = 1 << 18 > return 'Blog post body (no longer than %s bytes)' % max_bodylen > > @colander.deferred > def deferred_body_widget(node, **kw): > body_type = kw.get('body_type') > if body_type == 'richtext': > widget = deform.widget.RichTextWidget() > else: > widget = deform.widget.TextAreaWidget() > return widget > > @colander.deferred > def deferred_category_validator(node, **kw): > categories = kw.get('categories', []) > return colander.OneOf([ x[0] for x in categories ]) > > @colander.deferred > def deferred_category_widget(node, **kw): > categories = kw.get('categories', []) > return deform.widget.RadioChoiceWidget(values=categories) > > class BlogPostSchema(Schema): > title = SchemaNode( > colander.String(), > title = 'Title', > description = 'Blog post title', > validator = colander.Length(min=5, max=100), > widget = deform.widget.TextInputWidget(), > ) > date = SchemaNode( > colander.Date(), > title = 'Date', > missing = deferred_date_missing, > description = deferred_date_description, > validator = deferred_date_validator, > widget = deform.widget.DateInputWidget(), > ) > body = SchemaNode( > colander.String(), > title = 'Body', > description = deferred_body_description, > validator = deferred_body_validator, > widget = deferred_body_widget, > ) > category = SchemaNode( > colander.String(), > title = 'Category', > description = 'Blog post category', > validator = deferred_category_validator, > widget = deferred_category_widget, > ) > > schema = BlogPostSchema().bind( > max_date = datetime.date.max, > max_bodylen = 5000, > body_type = 'richtext', > default_date = datetime.date.today(), > ) > form = deform.Form(schema) > """ > > This proposal does not deal with conditional inclusion or exclusion of > schema nodes, only resolving deferred schema properties. > > Comments are appreciated. > > - C > > > > > On Tue, 2010-09-07 at 20:37 +0800, Tim Hoffman wrote: > > Bummer ;-) > > > > > > I don't think I have a developed an application in the last 10 years > > that hasn't has to do this. > > I was quite surprised when I discovered this feature was missing in > > formish, but it seems to be missing in quite a > > few other form libs like wtforms as well. > > > > I suppose at least they all have declarative method of defining the > > schema, but it does mean the actual schema definition is a bit more > > obscured. > > > > Cheers > > > > T > > > > > > > > > > On Tue, Sep 7, 2010 at 8:20 PM, Chris McDonough <chr...@plope.com> wrote: > > > Hi Tim, > > > > > > Sorry, there is no built-in solution that will allow you to use > > > declarative-module-scope code only. You'll need to generate schemas and > > > widgets at render time. > > > > > > - C > > > > > > > > > On Tue, 2010-09-07 at 12:56 +0800, Tim Hoffman wrote: > > >> Hi Chris. > > >> > > >> Am just starting too look at deform in some detail and I have question. > > >> > > >> One of the things I have struggled with formish has been the fact I > > >> can't easily > > >> define a source of values for widgets like checkbox or validators such > > >> as OneOf to > > >> only be resolved late at render time. And I can't see how I would go > > >> about it with deform. > > >> > > >> In your example http://docs.repoze.org/deform/app.html you have > > >> colors = (('red', 'Red'), ('green', 'Green'), ('blue', 'Blue')) used > > >> as values for > > >> > > >> widget.RadioChoiceWidget values and for the validator OneOf > > >> > > >> So in my contrived example I would like the set of possible values > > >> for color is dependent on the > > >> user and some other factor. Looking at the code for SelectWidget and > > >> RadioChoice widget > > >> it appears they won't take a callable and lazily render those values > > >> at render time. > > >> > > >> > > >> With formish I basically constructed the form structure (schema) > > >> but only applied widget definitions and validators just before render > > >> time. So that I could use things > > >> like the current context to determine values for validation or > > >> choices. This was a bit of a hack. > > >> > > >> > > >> So do you have a strategy or suggestion on how to approach this use case > > >> ? > > >> > > >> I suppose I could work with imperative schema definition performed > > >> late, but I much prefer to work with classes. > > >> (I currently generate Formish (structures) directly from UML). > > >> > > >> Cheers > > >> > > >> Tim > > >> _______________________________________________ > > >> Repoze-dev mailing list > > >> Repoze-dev@lists.repoze.org > > >> http://lists.repoze.org/listinfo/repoze-dev > > >> > > > > > > > > > > > > _______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev