Thursday, December 24, 2015

Using Decorators to Validate Flask Views

Flask is an awesome micro-framework and a great way of handling http requests when creating web apis.  What I'm proposing here is that custom Python decorators can make development of such projects even better.

Consider, for example, the http requests that post of json data.



What do we have here?  The model is an interface to the database.  It sends an exercise id and score to be persisted to it.  However, the get method calls on those json dictionaries can and will return None if there is no matching key.  Consequently, there is the potential for empty values to be inserted into the database.  We don't want that.  What to do then?

Validating Without A Decorator


One option is to look to make sure the keys are there and abort the api call with a 400 error.  Since status code 400 signals a bad request, the client will find out that the request bombed because they submitted the request incorrectly.  That would look something like this.


Validating With A So-So Decorator


The validation in the example above can be a little distracting.  Code is read more than written.  Extra safeguards are wise but also kind of distracts from the main point of what the function is ultimately trying to do.  So let's try a simple decorator and offload validation to there.




Not bad.  The only thing to bear in mind is that decorators are being chained together in this context.  The top decorator decorates the function that results from the decorators below it.  Flask is a framework.  We want it to register the final result of our customization with minimum confusion for all parties concerned.  For that reason, you generally want put the Flask routing decorator on top.

Generating Decorators


We're not done yet.  What about the other Flask functions dealing with json data?  Do ALL the json requests passed in to other functions use the exact same keys?  If not, the decorator we made so far won't work on those functions. We could create separate decorators specific to the keys of each function's json arguments.  Unfortunately,we'd end up with the very code repetition we've been trying to avoid.  What to do then?

One solution would be to write code to automate the creation of decorators that fit each target function's validation needs.  So what we need is something that creates other decorators.  When we do that, the end result is a decorator that takes arguments.  Here's what that looks like.


Not bad!  Not bad at all.  Accepting a variable length argument list allows us to put in as many string arguments as needed for the keys that need checking.  Those arguments strings are used to create a custom decorator on the fly.  That newly created decorator wraps the function we're targeting.  As a result, we now have a special kind of decorator that can be used to validate any json data at all.  Just specify the names of the keys and you're golden.

More Resources

There's a lot about decorators that hasn't been covered in this blog post.  Here are some other angles on what I've written about here.