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

Reply via email to