Book Image

Building RESTful Python Web Services

By : Gaston C. Hillar
Book Image

Building RESTful Python Web Services

By: Gaston C. Hillar

Overview of this book

Python is the language of choice for millions of developers worldwide, due to its gentle learning curve as well as its vast applications in day-to-day programming. It serves the purpose of building great web services in the RESTful architecture. This book will show you the best tools you can use to build your own web services. Learn how to develop RESTful APIs using the popular Python frameworks and all the necessary stacks with Python, Django, Flask, and Tornado, combined with related libraries and tools. We will dive deep into each of these frameworks to build various web services, and will provide use cases and best practices on when to use a particular framework to get the best results. We will show you everything required to successfully develop RESTful APIs with the four frameworks such as request handling, URL mapping, serialization, validation, authentication, authorization, versioning, ORMs, databases, custom code for models and views, and asynchronous callbacks. At the end of each framework, we will add authentication and security to the RESTful APIs and prepare tests for it. By the end of the book, you will have a deep understanding of the stacks needed to build RESTful web services.
Table of Contents (18 chapters)
Building RESTful Python Web Services
Credits
About the Author
Acknowledgments
About the Reviewer
www.PacktPub.com
Preface

Creating the models


Now, we will create a simple Game model that we will use to represent and persist games. Open the games/models.py file. The following lines show the initial code for this file, with just one import statement and a comment that indicates we should create the models:

from django.db import models 
 
# Create your models here. 

The following lines show the new code that creates a Game class, specifically, a Game model in the games/models.py file. The code file for the sample is included in the restful_python_chapter_01_01 folder:

from django.db import models 
 
 
class Game(models.Model): 
    created = models.DateTimeField(auto_now_add=True) 
    name = models.CharField(max_length=200, blank=True, default='') 
    release_date = models.DateTimeField() 
    game_category = models.CharField(max_length=200, blank=True, default='') 
    played = models.BooleanField(default=False) 
 
    class Meta: 
        ordering = ('name',) 

The Game class is a subclass of the django.db.models.Model class. Each defined attribute represents a database column or field. Django automatically adds an auto-increment integer primary key column named id when it creates the database table related to the model. However, the model maps the underlying id column in an attribute named pk for the model. We specified the field types, maximum lengths and defaults for many attributes. The class declares a Meta inner class that declares a ordering attribute and sets its value to a tuple of string whose first value is the 'name' string, indicating that, by default, we want the results ordered by the name attribute in ascending order.

Then, it is necessary to create the initial migration for the new Game model we recently coded. We just need to run the following Python scripts and we will also synchronize the database for the first time. By default, Django uses an SQLite database. In this example, we will be working with this default configuration:

python manage.py makemigrations games

The following lines show the output generated after running the preceding command.

Migrations for 'games':
  0001_initial.py:
    - Create model Game

The output indicates that the gamesapi/games/migrations/0001_initial.py file includes the code to create the Game model. The following lines show the code for this file that was automatically generated by Django. The code file for the sample is included in the restful_python_chapter_01_01 folder:

# -*- coding: utf-8 -*- 
# Generated by Django 1.9.6 on 2016-05-17 21:19 
from __future__ import unicode_literals 
 
from django.db import migrations, models 
 
 
class Migration(migrations.Migration): 
 
    initial = True 
 
    dependencies = [ 
    ] 
 
    operations = [ 
        migrations.CreateModel( 
            name='Game', 
            fields=[ 
                ('id', models.AutoField(auto_created=True, primary_key=True,
                serialize=False, verbose_name='ID')), 
                ('created', models.DateTimeField(auto_now_add=True)), 
                ('name', models.CharField(blank=True, default='',
                 max_length=200)), 
                ('release_date', models.DateTimeField()), 
                ('game_category', models.CharField(blank=True, default='',
                 max_length=200)), 
                ('played', models.BooleanField(default=False)), 
            ], 
            options={ 
                'ordering': ('name',), 
            }, 
        ), 
    ] 

The code defines a subclass of the django.db.migrations.Migration class named Migration that defines an operation that creates the Game model's table. Now, run the following python script to apply all the generated migrations:

python manage.py migrate

The following lines show the output generated after running the preceding command:

Operations to perform:
  Apply all migrations: sessions, games, contenttypes, admin, auth
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying games.0001_initial... OK
  Applying sessions.0001_initial... OK

After we run the preceding command, we will notice that the root folder for our gamesapi project now has a db.sqlite3 file. We can use the SQLite command line or any other application that allows us to easily check the contents of the SQLite database to check the tables that Django generated.

In macOS and most modern Linux distributions, SQLite is already installed, and therefore, you can run the sqlite3 command-line utility. However, in Windows, if you want to work with the sqlite3.exe command-line utility, you will have to download and install SQLite from its Web page-http://www.sqlite.org.

Run the following command to list the generated tables:

sqlite3 db.sqlite3 '.tables'

Run the following command to retrieve the SQL used to create the games_game table:

sqlite3 db.sqlite3 '.schema games_game'

The following command will allow you to check the contents of the games_game table after we compose and send HTTP requests to the RESTful API and make CRUD operations to the games_game table:

sqlite3 db.sqlite3 'SELECT * FROM games_game ORDER BY name;'

Instead of working with the SQLite command-line utility, you can use a GUI tool to check the contents of the SQLite database. DB Browser for SQLite is a useful multiplatform and free GUI tool that allows us to easily check the database contents of an SQLite database in macOS, Linux and Windows. You can read more information about this tool and download its different versions from http://sqlitebrowser.org. Once you installed the tool, you just need to open the db.sqlite3 file and you can check the database structure and browse the data for the different tables. You can use also the database tools included in your favorite IDE to check the contents for the SQLite database.

The SQLite database engine and the database file name are specified in the gamesapi/settings.py Python file. The following lines show the declaration of the DATABASES dictionary that contains the settings for all the database that Django uses. The nested dictionary maps the database named default with the django.db.backends.sqlite3 database engine and the db.sqlite3 database file located in the BASE_DIR folder (gamesapi):

DATABASES = { 
    'default': { 
        'ENGINE': 'django.db.backends.sqlite3', 
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 
    } 
} 

After we executed the migrations, the SQLite database will have the following tables:

  • auth_group

  • auth_group_permissions

  • auth_permission

  • auth_user

  • auth_user_groups

  • auth_user_groups_permissions

  • django_admin_log

  • django_content_type

  • django_migrations

  • django_session

  • games_game

  • sqlite_sequence

The games_game table persists in the database the Game class we recently created, specifically, the Game model. Django's integrated ORM generated the games_game table based on our Game model. The games_game table has the following rows (also known as fields) with their SQLite types and all of them are not nullable:

  • id: The integer primary key, an autoincrement row

  • created: datetime

  • name: varchar(200)

  • release_date: datetime

  • game_category: varchar(200)

  • played: bool

The following lines show the SQL creation script that Django generated when we executed the migrations:

CREATE TABLE "games_game" ( 
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "created" datetime NOT NULL, 
    "name" varchar(200) NOT NULL, 
    "release_date" datetime NOT NULL, 
    "game_category" varchar(200) NOT NULL, 
    "played" bool NOT NULL 
) 

Django generated additional tables that it requires to support the Web framework and the authentication features that we will use later.