Proper way to manually raise deform ValidationFailure from view?

236 views
Skip to first unread message

pyramidX

unread,
Jan 2, 2015, 8:55:54 AM1/2/15
to pylons-...@googlegroups.com
What is the correct way to manually raise a deform.exception.ValidationFailure from a view, to set a particular field as having an invalid value? I don't want to create a custom validator because there are many situations where you want the application logic to be in the view not in a form validation function.

I can set up the errors directly on the form itself, which gets the error messages to render to the form html.

    form.error = colander.Invalid(None, 'Error message on form')
    form
['some_field'].error = colander.Invalid(None, 'Error message on field')
   
raise deform.exception.ValidationFailure(form, None, form.error)

But the problem is that I can't unit test this manually-thrown ValidationFailure in the same way as the ones thrown by deform. In other situations I can make assertions like the following

        assert len(e.error.children) == 1
       
assert e.error.children[0].asdict()['some_field'] == 'Error message on field'
 
But in the above case 'e.error.children' is an empty list. How do I raise the ValidationFailure consistently with ones thrown by deform?

I can do it like the following, and everything gets set up identical to when deform does it (including populating the 'pos' attribute on colander.Invalid. However, now the errors aren't getting rendered to the form html.

    e = colander.Invalid(form.schema, 'Error message on form')
    e
['some_field'] = 'Error message on field'
   
raise deform.exception.ValidationFailure(form, None, e)

The only way I can get it to work is like the following, now the object gets created correctly and it renders properly on the page. Here I am assigning the Invalid errors to the schema then re-assigning them to the correct place in the form. But this is not DRY and seems quite hack-ish. (Especially the 4th line, were I can't retrieve the created child Invalid by doing e.children['some_field'] but have to get it using the numerical index.) This tells me I'm probably not raising this ValidationFailure properly.

What is the correct way to be doing this in a DRY way?

    e = colander.Invalid(form.schema, 'Error message on form')
    e
['some_field'] = 'Error message on field'
    form
.error = e
    form
['some_field'].error = e.children[0]
   
raise deform.exception.ValidationFailure(form, None, form.error)

ngoone...@gmail.com

unread,
Nov 18, 2016, 5:45:00 AM11/18/16
to pylons-discuss
Thanks for your post, really helped me to do the same thing in my project. I'm not unit-testing this portion of my project so I just used the first implementation. However I dug abit into the current source, and I believe calling form.widget.handle_error should work.

So for your final example...

    e = colander.Invalid(form.schema, 'Error message on form')
    e
['some_field'] = 'Error message on field'
    form
.error =
e
    form.widget.handle_error(form, e)  # This is the crucial line

   
raise deform.exception.ValidationFailure(form, None, form.error)
Reply all
Reply to author
Forward
0 new messages