deform
deform copied to clipboard
form.render(appstruct) is not respected if form.validate() was called before
I've had this problem in my application, where this is a reduction from.
The problem is that calling form.validate(post_values)
before calling form.render(app_struct)
leaves turds in the fields (to quote mcdonc from irc). In practice that means that the app_struct from form.render() is ignored for some values
On IRC mcdonc pointed to this code as being the offender: https://github.com/Pylons/deform/blob/master/deform/widget.py#L1497
Here's the reduction that shows the issue.
#!/usr/bin/env python
import colander
import deform
from deform.widget import TextAreaWidget, SequenceWidget
class AnswerEditSchema(colander.Schema):
answer_title = colander.SchemaNode(
colander.String(),
validator=colander.Length(1, 384),
title=u"Title",
missing=u'',
widget=deform.widget.TextAreaWidget(),
)
class QuestionEditSchema(colander.Schema):
question_title = colander.SchemaNode(
colander.String(),
validator=colander.Length(2),
title=u"Title",
widget=deform.widget.TextAreaWidget(),
)
answers = colander.SchemaNode(
colander.Sequence(),
AnswerEditSchema(
title=u"Answer",
name=u"answer"
),
widget=SequenceWidget(min_len=2),
title=u"Answers",
)
schema = QuestionEditSchema().bind()
form = deform.Form(schema=schema)
post_values = [('_charset_', u'UTF-8'), ('question_title', u'english title'), ('__start__', u'answers:sequence'), ('__start__', u':mapping'), ('title', u''), ('__end__', u':mapping'), ('__start__', u':mapping'), ('title', u'english wrong answer'), ('__end__', u':mapping'), ('__end__', u'answers:sequence'), ('submit', u'submit')]
app_struct = form.validate(post_values)
# app_struct = {'answers': [{'answer_title': 'fnord1'}, {'answer_title': u'english wrong answer'}], 'question_title': 'fnord2'}
print 'app_struct:\t', app_struct
app_struct['question_title'] = 'fnord1'
app_struct['answers'][0]['answer_title'] = 'fnord2'
print 'new app struct:\t', app_struct
rendered = form.render(app_struct)
assert 'fnord1' in rendered, "form.render() does not respect app_struct['question_title']" # this works
assert 'fnord2' in rendered, "form.render() does not respect app_struct['answers'][0]['answer_title']" # this doesn't
I was just about to open a ticket for exactly this problem.
In my case I am storing the objects in a database after the validation, and the objects will receive their primary keys. But then, if I am rendering the form, the objects in a SequenceWidget
will not have the new primary key.
As a work-around you can simply create a fresh form object, but it would be nice if validate
would not leave turds in the fields.