Hi Chris On the face of it, it looks pretty good.
I hope to be in a position to swap out formish and give it a go in a few weeks, T On Thu, Sep 9, 2010 at 4:57 AM, Chris McDonough <chr...@plope.com> wrote: > 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