Reader small image

You're reading from  Building RESTful Python Web Services

Product typeBook
Published inOct 2016
Reading LevelIntermediate
PublisherPackt
ISBN-139781786462251
Edition1st Edition
Languages
Concepts
Right arrow
Author (1)
Gaston C. Hillar
Gaston C. Hillar
author image
Gaston C. Hillar

Gaston C. Hillar is Italian and has been working with computers since he was 8 years old. Gaston has a Bachelor's degree in computer science (graduated with honors) and an MBA. Currently, Gaston is an independent IT consultant and a freelance author who is always looking for new adventures anywhere in the world. He was a senior contributing editor at Dr. Dobb's, and has written more than a hundred articles on software development topics. He has received the prestigious Intel Black Belt Software Developer award eight times. He has written many articles about Java for Oracle Java Magazine. Gaston was also a former Microsoft MVP in technical computing. He lives with his wife, Vanesa, and his two sons, Kevin and Brandon.
Read more about Gaston C. Hillar

Right arrow

Chapter 6.  Working with Models, SQLAlchemy, and Hyperlinked APIs in Flask

In this chapter, we will expand the capabilities of the RESTful API that we started in the previous chapter. We will use SQLAlchemy as our ORM to work with a PostgreSQL database and we will take advantage of advanced features included in Flask and Flask-RESTful that will allow us to easily organize code for complex APIs, such as models and blueprints. In this chapter, we will:

  • Design a RESTful API to interact with a PostgreSQL database

  • Understand the tasks performed by each HTTP method

  • Install packages to simplify our common tasks

  • Create and configure the database

  • Write code for the models with their relationships

  • Use schemas to validate, serialize, and deserialize models

  • Combine blueprints with resourceful routing

  • Register the blueprint and run migrations

  • Create and retrieve related resources

Designing a RESTful API to interact with a PostgreSQL database


So far, our RESTful API has performed CRUD operations on a simple dictionary that acted as a data repository. Now, we want to create a more complex RESTful API with Flask RESTful to interact with a database model that has to allow us to work with messages that are grouped into message categories. In our previous RESTful API, we used a string attribute to specify the message category for a message. In this case, we want to be able to easily retrieve all the messages that belong to a specific message category, and therefore, we will have a relationship between a message and a message category.

We must be able to perform CRUD operations on different related resources and resource collections. The following list enumerates the resources and the class name that we will create to represent the model:

  • Message categories (Category model)

  • Messages (Message model)

The message category (Category) just requires an integer name, and we need the...

Understanding the tasks performed by each HTTP method


The following table shows the HTTP verbs, the scope, and the semantics for the methods that our new API must support. Each method is composed of an HTTP verb, a scope, and all the methods have well-defined meanings for all the resources and collections:

Installing packages to simplify our common tasks


Make sure you quit Flask's development server. Remember that you just need to press Ctrl + C in the Terminal or Command Prompt window in which it is running. Now, we will install many additional packages. Make sure you have activated the virtual environment we have created in the previous chapter and we named Flask01. In case you created a new virtual environment to work with this example or you downloaded the sample code for the book, make sure you install the packages we used in the previous example.

After you activate the virtual environment, it is time to run commands that will be the same for either macOS, Linux, or Windows. We can install all the necessary packages with pip with a single command. However, we will run independent commands to make it easier to detect any problems in case a specific installation fails.

Now, we must run the following command to install Flask-SQLAlchemy with pip. Flask-SQLAlchemy adds support for the SQLAlchemy...

Creating and configuring the database


Now, we will create the PostgreSQL database that we will use as a repository for our API. You will have to download and install a PostgreSQL database in case you aren't already running it in your computer or in a development server. You can download and install this database management system from its web page: http://www.postgresql.org. In case you are working with macOS, Postgres.app provides a really easy way to install and use PostgreSQL on this operating system: http://postgresapp.com:

Tip

You have to make sure that the PostgreSQL bin folder is included in the PATH environmental variable. You should be able to execute the psql command-line utility from your current Terminal or Command Prompt. In case the folder isn't included in the PATH, you will receive an error indicating that the pg_config file cannot be found when trying to install the psycopg2 package. In addition, you will have to use the full path to each of the PostgreSQL command-line tools...

Creating models with their relationships


Now, we will create the models that we can use to represent and persist the message categories, messages, and their relationships. Open the api/models.py file and replace its contents with the following code. The lines that declare fields related to other models are highlighted in the code listing. In case you created a new virtual environment, create a new models.py file within the api folder. The code file for the sample is included in the restful_python_chapter_06_01 folder:

from marshmallow import Schema, fields, pre_load 
from marshmallow import validate 
from flask_sqlalchemy import SQLAlchemy 
from flask_marshmallow import Marshmallow 
 
 
db = SQLAlchemy() 
ma = Marshmallow() 
 
 
class AddUpdateDelete():    
    def add(self, resource): 
        db.session.add(resource) 
        return db.session.commit() 
 
    def update(self): 
        return db.session.commit() 
 
    def delete(self, resource): 
        db.session.delete(resource) 
 ...

Creating schemas to validate, serialize, and deserialize models


Now, we will create the Flask-Marshmallow schemas that we will use to validate, serialize, and deserialize the previously declared Category and Message models and their relationships. Open the api/models.py file and add the following code after the existing lines. The lines that declare the fields related to the other schemas are highlighted in the code listing. The code file for the sample is included in the restful_python_chapter_06_01 folder:

class CategorySchema(ma.Schema): 
    id = fields.Integer(dump_only=True) 
    name = fields.String(required=True, validate=validate.Length(3)) 
    url = ma.URLFor('api.categoryresource', id='<id>', _external=True) 
    messages = fields.Nested('MessageSchema', many=True, exclude=('category',)) 
 
 class MessageSchema(ma.Schema): 
    id = fields.Integer(dump_only=True) 
    message = fields.String(required=True, validate=validate.Length(1)) 
    duration = fields.Integer() 
 ...

Combining blueprints with resourceful routing


Now, we will create the resources that compose our main building blocks for the RESTful API. First, we will create a few instances that we will use in the different resources. Then, we will create a MessageResource class, that we will use to represent the message resource. Create a new views.py file within the api folder and add the following lines. The code file for the sample is included in the restful_python_chapter_06_01 folder, as shown:

from flask import Blueprint, request, jsonify, make_response 
from flask_restful import Api, Resource 
from models import db, Category, CategorySchema, Message, MessageSchema 
from sqlalchemy.exc import SQLAlchemyError 
import status 
 
 
api_bp = Blueprint('api', __name__) 
category_schema = CategorySchema() 
message_schema = MessageSchema() 
api = Api(api_bp) 
 
 
class MessageResource(Resource): 
    def get(self, id): 
        message = Message.query.get_or_404(id) 
        result = message_schema.dump...

Registering the blueprint and running migrations


Create a new app.py file within the api folder. The following lines show the code that creates a Flask application. The code file for the sample is included in the restful_python_chapter_06_01 folder.

from flask import Flask 
 
 
def create_app(config_filename): 
    app = Flask(__name__) 
    app.config.from_object(config_filename) 
 
    from models import db 
    db.init_app(app) 
 
    from views import api_bp 
    app.register_blueprint(api_bp, url_prefix='/api') 
 
    return app 

The code in the api/app.py file declares a create_app function that receives the configuration file name in the config_filename argument, set ups a Flask app with this configuration file, and returns the app object. First, the function creates the main entry point for the Flask application named app. Then, the code calls the app.config.from_object method with the config_filename received as an argument. This way, the Flask app uses the values that are specified...

Test your knowledge


  1. Marshmallow is:

    1. A lightweight library for converting complex datatypes to and from native Python datatypes.

    2. An ORM .

    3. A lightweight web framework that replaces Flask.

  2. SQLAlchemy is:

    1. A lightweight library for converting complex datatypes to and from native Python datatypes.

    2. An ORM .

    3. A lightweight web framework that replaces Flask.

  3. The marshmallow.pre_load decorator:

    1. Registers a method to run after any instance of the MessageSchema class is created.

    2. Registers a method to invoke after serializing an object.

    3. Registers a method to invoke before deserializing an object.

  4. The dump method for any instance of a Schema subclass:

    1. Routes URLs to Python primitives.

    2. Persists the instance or collection of instances passed as an argument to the database.

    3. Takes the instance or collection of instances passed as an argument and applies the field filtering and output formatting specified in the Schema subclass to the instance or collection of instances.

  5. When we declare an attribute as an instance...

Summary


In this chapter, we expanded the capabilities of the previous version of the RESTful API that we created in the previous chapter. We used SQLAlchemy as our ORM to work with a PostgreSQL database. We installed many packages to simplify many common tasks, wrote code for the models and their relationships, and worked with schemas to validate, serialize, and deserialize these models.

We combined blueprints with resourceful routing and were able to generate the database from the models. We composed and sent many HTTP requests to our RESTful API and analyzed how each HTTP request was processed in our code and how the models persisted in the database tables.

Now that we built a complex API with Flask, Flask-RESTful, and SQLAlchemy, we will use additional features and add security and authentication, which is what we are going to discuss in the next chapter.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Building RESTful Python Web Services
Published in: Oct 2016Publisher: PacktISBN-13: 9781786462251
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Gaston C. Hillar

Gaston C. Hillar is Italian and has been working with computers since he was 8 years old. Gaston has a Bachelor's degree in computer science (graduated with honors) and an MBA. Currently, Gaston is an independent IT consultant and a freelance author who is always looking for new adventures anywhere in the world. He was a senior contributing editor at Dr. Dobb's, and has written more than a hundred articles on software development topics. He has received the prestigious Intel Black Belt Software Developer award eight times. He has written many articles about Java for Oracle Java Magazine. Gaston was also a former Microsoft MVP in technical computing. He lives with his wife, Vanesa, and his two sons, Kevin and Brandon.
Read more about Gaston C. Hillar

HTTP verb

Scope

Semantics

GET

Collection of message categories

Retrieve all the stored message categories in the collection and return them sorted by their name in ascending order. Each category must include the full URL for the resource. Each category must include a list with all the details for the messages that belong to the category. The messages don't have to include the category in order to avoid repeating data.

GET

Message category

Retrieve a single message category. The category must include the same information explained for each category when we retrieve a collection of message category.

POST

Collection of message categories

Create a new message category...