Am 25.06.2012 12:53, schrieb Alessandro Molina:
I think it is probably a tw2 bug as the right behavior is the one you
get when you don't specify the id. The id of the root element should
probably not be added to the field names.

As far as I understand that's considered a feature of TW2, not a bug (see http://tw2core.readthedocs.org/en/latest/history/#consistency-in-ids-and-names)

About the fieldset behavior, that is the expected one. If I'm not
wrong, It was like that also on TW1.
To unpack the arguments you just have to add @validate(MovieForm) to
your index controllers and it will receive the arguments in nested
dictionaries instead of multiple arguments separated by colon.

Adding @validate should fix also the behavior with ID as it will
unpack those too.

Thanks, you're right with that - @validate calls unflatten_params(), which converts everything to a nested dict. This solves the problem properly, and makes the above feature/bug a non-issue. Removing the id was not such a good solution, because the generated ids of the fields could then become ambiguous. I had totally forgotten about that feature, as in TW1 it was only important for fieldsets. We should emphasize this explicitly in the docs.

By the way, is anybody working on a TW2 version of the forms tutorial (http://turbogears.org/2.1/docs/main/ToscaWidgets/forms.html) already? If not, I'm volunteering to do it.

I just noticed another peculiarity with TW2. Take again the following controller methods from the forms tutorial as example:

    @expose('.templates.new_form')
    def new(self, **kw):
        tmpl_context.form = MovieForm()
        return dict(modelname='Movie', value=kw)

    @validate(MovieForm, error_handler=new)
    @expose()
    def create(self, **kw):
        movie = Movie()
        movie.title = kw['title']
        movie.year = kw['year']
        movie.release_date = kw['release_date']
        movie.description = kw['description']
        movie.genre = kw['genre']
        DBSession.add(movie)
        redirect('list')

The new_form template displays the form like this:

<div py:replace="tmpl_context.form.display(value=value)"/>

Note that contrary to the TW1 version, we create a new instance of the MovieForm widget on every request, because this is the way widgets should actually be used in TW2 (see http://tw2core.readthedocs.org/en/latest/history/#per-request-widget-instances).

However, if you do this, you will notice that no error messages will show up for the validated fields of the form, even though tmpl_context.from_errors is populated properly.

The reason is simple: The error messages are taken from the widget instance that is displayed, not from tmpl_context.form_errors. And since we always create a fresh instance, no errors will be set.

For similar reasons, the values that the user has already entered will not show up when the form is re-displayed after an error.

The errors and values are set as members of a different widget instance that is created during the validation process. Luckily, TW2 stores that validated instance request local and will pick it up again when display() is called as a class method. When no validated instance is available for the request, a new instance will be created.

So the proper usage of TW2 is to pass a form class to the page template, not a form instance:

    @expose('.templates.new_form')
    def new(self, **kw):
        tmpl_context.form = MovieForm
        return dict(modelname='Movie', value=kw)

This is another thing that we need to document properly, as it is not really obvious.

-- Christoph

--
You received this message because you are subscribed to the Google Groups 
"TurboGears" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/turbogears?hl=en.

Reply via email to