What's the right way to do form validation?

412 views
Skip to first unread message

Nick Baum

unread,
Nov 3, 2012, 1:06:32 PM11/3/12
to python-...@googlegroups.com
Hi,

I'm looking for advice on to how to best implement form validation in Tornado.

My original pseudo code went something like

def post(self):
    a = self.get_argument("a")
    b = self.get_argument("b")
    [...]
    db.doStuff(a, b)
    self.render("success.html")

def write_error(self, status_code, **kwargs):
    self.render("template.html", error=status_code)

This was nice and clean because get_argument throws exceptions if an argument was missing.

Unfortunately, two things are wrong with it:
  • There's no easy way to know what argument was missing when rendering the error (short of parsing the error message), so there's no way to display the error next to the corresponding form field
  • An error loses all the entered information, unless I parse all the arguments and feed them back in to the template.
Now I have something like this:

def get(self, error=None, data=None):
    if not data:
        data = self.get_data()
    self.render("template.html", error=error, data=data)

def post(self):
    data = self.get_data()
    if data["a"] == "":
        self.get(error="missing a", data)
        return
    [...]
    db.doStuff(data["a"], data["b"])
    self.render("success.html")

def get_data(self):
    data = {}
    data["a"] = self.get_argument("a", "")
    [...]

However, this feels awfully clunky to me – verbose if...return checks, data["..."] everywhere. Is there a more elegant way to do this?

One possibility: (a) override get_argument to throw an exception that includes the argument name (b) override write_error to handle these exceptions (c) use get_argument in the template to preserve the data.

Thanks,

-Nick

aliane abdelouahab

unread,
Nov 4, 2012, 5:39:23 AM11/4/12
to Tornado Web Server
some ideas:
use len(a), so if there is not a then len = 0
use templates with True or False, because then it's True, the value
will be 1 and in strings, "word"*1="word", else it will be an empty
string: "word"*0=""
use Raise to raise an error.

On 3 nov, 18:06, Nick Baum <nickb...@whereberry.com> wrote:
> Hi,
>
> I'm looking for advice on to how to best implement form validation in
> Tornado.
>
> My original pseudo code went something like
>
> def post(self):
>     a = self.get_argument("a")
>     b = self.get_argument("b")
>     [...]
>     db.doStuff(a, b)
>     self.render("success.html")
>
> def write_error(self, status_code, **kwargs):
>     self.render("template.html", error=status_code)
>
> This was nice and clean because get_argument throws exceptions if an
> argument was missing.
>
> Unfortunately, two things are wrong with it:
>
>    - There's no easy way to know what argument was missing when rendering
>    the error (short of parsing the error message), so there's no way to
>    display the error next to the corresponding form field
>    - An error loses all the entered information, unless I parse all the

messense

unread,
Nov 4, 2012, 2:24:33 AM11/4/12
to python-...@googlegroups.com
I think this article may help you.


-- 
messense
已使用 Sparrow

Ben Darnell

unread,
Nov 4, 2012, 10:26:02 AM11/4/12
to Tornado Mailing List
Including the argument name in the exception is a good idea in general, but even with that it's not very user-friendly to validate forms by throwing exceptions, since you can only report one error at a time this way.  I think I would actually recommend doing validation in javascript (at least for things like missing required parameters) to provide good error messages, and then the server can do its own validation but doesn't need to worry as much about messaging.  Wherever you do the validation, you probably want a method (like get_data()) to collect the form parameters into one object, and also accumulate a list of errors as it goes (e.g. "data, errors = self.get_data(); if errors: self.render("template.html", errors=errors, data=data)")

aliane abdelouahab

unread,
Nov 4, 2012, 10:28:21 AM11/4/12
to Tornado Web Server
about using Javascript, in HTML5 this will make it easier.
here is a question i've asked how to make a way to trust the client
from the server
http://stackoverflow.com/questions/13160340/how-to-make-that-the-server-trust-client-side-validation
> >    - There's no easy way to know what argument was missing when rendering
> >    the error (short of parsing the error message), so there's no way to
> >    display the error next to the corresponding form field
> >    - An error loses all the entered information, unless I parse all the

Nick Baum

unread,
Nov 7, 2012, 3:01:15 AM11/7/12
to Tornado
Thanks for the replies. All in all, it seems that my basic approach of (a) parse values (b) validate values and collect errors (c) pass values and errors back into template is roughly right, even though it's not particularly elegant.

I'm planning to add JS validation down the line, but for now I'm avoiding the additional complexity. I deliberately don't accumulate errors as I prefer to display one error at a time rather than a form filled with red.

Cheers,

-Nick
--
Nick Baum
Founder, WhereBerry Inc.

Lysander Trischler

unread,
Nov 7, 2012, 4:14:03 AM11/7/12
to python-...@googlegroups.com
Hello,

> All in all, it seems that my basic approach of (a) parse values
> (b) validate values and collect errors (c) pass values and errors
> back into template is roughly right, even though it's not
> particularly elegant.

you could also have a look at WTForms¹. Personally I haven't used it yet but
looked at the docs some time ago and it looked quite nice. If you search this
mailinglist you will find some people using it and also how to integrate it
into Tornado. You have to write some glue to connect both together, mainly for
argument access and translation.

¹: http://wtforms.simplecodes.com/docs/1.0.2/

Regards,
Lyse

aliane abdelouahab

unread,
Nov 7, 2012, 6:27:56 AM11/7/12
to Tornado Web Server
dont forget that:
you will have a small probability that a user is a hacker that tries
to baypass you javascript.
javascript is here, to minimise your calls to the server, why forcing
server to make lot of calculation everytime you send to the client :
this is missing or wrong format...
personaly (am a beginner so i dont know if because am so) dont use
WTForms, regular expressions on it are fixed, so i think it would be
better to use its own Regexes to learn and take controle of speed.

On 7 nov, 09:01, Nick Baum <nickb...@whereberry.com> wrote:
> I'm planning to add JS validation down the line, but for now I'm avoiding
> the additional complexity. I deliberately don't accumulate errors as I
> prefer to display one error at a time rather than a form filled with red.
>
> Cheers,
>
> -Nick
>
> On Sun, Nov 4, 2012 at 7:28 AM, aliane abdelouahab
> <alabdeloua...@gmail.com>wrote:
>
>
>
>
>
>
>
>
>
> > about using Javascript, in HTML5 this will make it easier.
> > here is a question i've asked how to make a way to trust the client
> > from the server
>
> >http://stackoverflow.com/questions/13160340/how-to-make-that-the-serv...

aliane abdelouahab

unread,
Nov 7, 2012, 6:41:59 AM11/7/12
to Tornado Web Server
*use your own regex (eghhhhhhhh cant modify comments....nosql and
write-once-read-many)
Reply all
Reply to author
Forward
0 new messages