Hello all,
I have a fairly complex schema and a need to perform moderately complex
inter-field validation. As far as I can tell, the complex validation must
be performed at the lowest SchemaNode in the structure that is a parent of
both fields. That's fine, but I cannot see how to attach the resulting
errors to the actual fields themselves (so that when I render the error
form the error messages appear with the fields).
Here's an illustrative test schema. The idea is that if field
c.value_string is present, then field b.a_list.n.value_string is required
(for all n >= 0).
import colander
import deform.widget
OPTIONAL=colander.null
class A(colander.MappingSchema):
value_string = colander.SchemaNode(colander.String(), missing=OPTIONAL)
value_int = colander.SchemaNode(colander.Integer())
value_bool = colander.SchemaNode(colander.Boolean())
class AList(colander.SequenceSchema):
a = A()
class B(colander.MappingSchema):
a_list = AList()
class C(colander.MappingSchema):
value_string = colander.SchemaNode(colander.String(), missing=OPTIONAL)
class MySchema(colander.MappingSchema):
b = B()
c = C()
def validator(self, node, data):
if data["c"]["value_string"] is not colander.null:
for (pos, a) in enumerate(data["b"]["a_list"]):
if a["value_string"] is colander.null:
exc_node = node["b"]["a_list"]["a"]
exc = colander.Invalid(exc_node)
exc["value_string"] = "Required"
# Tried this but it won't fly
# exc["b"]["a_list"][pos]["value_string"] = "Required"
raise exc
initial_data = {
"c" : { "value_string" : "x" },
"b" : { "a_list" : [{
"value_string" : colander.null,
"value_int" : 1,
"value_bool" : False,
}]}
}
FWIW, this is the pyramid view that handles the form requests (it's pretty
vanilla and doesn't add much to the question, although we are using cheetah
templates to render the widgets):
class DeformTestView(object):
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
schema = portal.test.deform.test_schema.MySchema()
renderer = portal.deform.util.cheetah_renderer
submit_btn = deform.Button(title="Submit", css_class="span2")
submit_btn.id = "submit_button"
submit_btn.href = pyramid.url.resource_url(self.context,
self.request)
submit_btn.newwindow = False
form = deform.Form(
schema,
formid="data_entry_form", # default=deform, which breaks
deform.js
method="POST",
renderer=renderer,
buttons=[submit_btn],
)
form.widget.css_class = "deform small form-horizontal condensed"
if self.request.method == "GET":
return dict(
view=self,
deform_form=form.render(portal.test.deform.test_schema.initial_data)
)
if self.request.method == "POST":
try:
form_data = form.validate(self.request.POST.items())
except deform.ValidationFailure as error_form:
print "DeformTestView.__call__: validation exception: %s" %
str(error_form.error)
return dict (
view=self,
deform_form=error_form.render(),
)
return dict(
view=self,
deform_form=form.render(form_data)
)
The print in the POST case emits this:
DeformTestView.__call__: validation exception: {'a.value_string':
'Required'}
which is not particularly useful; I'd like it to look more like:
DeformTestView.__call__: validation exception: {'b.a_list.0.value_string':
'Required'}
but I cannot see what to do to make that happen.
Thanks,
Alistair
--
You received this message because you are subscribed to the Google Groups
"pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.