if not schema.validate(data): print(“Validation rules”)
When we implement an API it’s important to check whether the data we are receiving in an endpoint is the kind of data we are expecting. Even if you have developed some validation in the client side, you should not trust data coming from it. The mechanism of validation in the client side can have a bug or someone could be interacting directly with the API through curl or Postman and try to run malicious code such a SQL Injection attack.
If we validate our data we ensure that it is consistent, accurate and complete, so it will prevent for data loss and error during its manipulation. If we don’t validate the data in the API we can end up with malicious data, breaking the integrity of our database or sending back unuseful http responses.
What are we going to do
First, we are going to write a simple API with the classic CRUD (Create, Read, Update and Delete) for handling Social Events using Python (I think you had already guess it by the title of the article) with Flask (a lightweight web framework). I say simple because we are not going to configure any fancy thing such as SQLAlchemy (the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL) or implement a login system or tests as it would be out of the scope of the article.
Once implemented we will use marshmallow and we will compare the validation of data in both cases.
Configuration of initial server
Let’s suppose this are the requirements of the social events:
- name: The name of the event (required, no longer than 100 characters)
- description: The description of the event (required, no longer than 1000 characters)
- organizer: The organizer of the event (optional, no longer than 100 characters)
- datetime_of_ovent: The date and time of the event (required)
If you want to see the complete server you can visit my repository however, given that we are talking about validation of data, here we will see just the code for two endpoints, create and update, the ones that receive data.
Here is the relevant code:
Before we start talking about the validation I would like to point out how cool is the new feature released in Python 3.8, the walrus operator ( := ) which allows me to do an assignment expressions and save me one line :)
You can see what’s new in Python 3.8 in here. Now let’s validate!
As we can see in the code, we have to validate each parameter that we will be receiving and processing, we have to check if the required fields are present and if they meet the requirements.This is a small example with an entity that just has 4 parameters and it is making us to write a lot of lines, image if we have more complicated entities…
Here is when comes handy things like marshmallow:
marshmallow is an ORM/ODM/framework-agnostic library for converting complex datatypes, such as objects, to and from native Python datatypes.
In short, marshmallow schemas can be used to:
- Validate input data.
- Deserialize input data to app-level objects.
- Serialize app-level objects to primitive Python types. The serialized objects can then be rendered to standard formats such as JSON for use in an HTTP API.
As we can see, marshmallow is giving us the possibility to validate our input data. Neat!
Let see what should we do to use it.
First we write the Schemes for our Event model. We will implement one for the Create Event and another for the Update Event, as both have different required fields.
Then we can easily validate the data in our endpoints:
As we can see there are clearly less code to write :)
But for the moment this is just theory, let’s play with it and see how it works!
As we expected we can create an events as before:
However, if we try to create one with a field longer than required, a different type or if we miss a required parameter, marshmallow will tell us:
These are pretty straight forward checks, but what if we want to check more complicated things. What if we want to check if the date of the event is a date in the future and no more than one year in advance?
With marshmallow we can implement our own validation functions (you can check it out in the documentation) but for this example, we will write our validator as a method.
Let’s try it out:
Validation is a must. Is a good practice that should be implemented in any API as it will improve the security, make it more robust and it will offer a better interaction with it’s users giving them a better response explaining the errors.
If you want to check out the code used for this article you can visit my repository. The code for the first part is in the without-marshmallow branch, and the rest is in the marshmallow branch.
If you want to see a more complicated configuration with a real database an a ORM such as SQLAlchemy stay tuned for my next article where I will show you how to do it.