Skip to content
Alexis ROLLAND edited this page Feb 2, 2018 · 67 revisions

Flask Graphene SQLAlchemy Tutorial

Introduction

The objective of this tutorial is to describe step by step how to create a GraphQL API using Python and more specifically the following packages:

The API will expose data coming from an SQLite database stored locally on your machine. The end result will follow the logical architecture described in the schema below.

Architecture

Workstation set-up

Install third party Python packages mentioned by running the following commands.

$ cd flask-graphene-sqlalchemy
$ pip3 install -r requirements.txt

Create the database

The database will contain some Planet and People data from Star Wars, stored in 2 different tables (data source: The Star Wars API):

  • Planet: List of planets appearing in Star Wars movies
  • People: List of people appearing in Star Wars movies

Note there is a relationship between planets and people as one planet is the homeworld of one or several persons in the people table. It is a "one-to-many" relationship (one planet, many people). The homeworld column in the people table will be used as foreign key of the planet and as such will contain the planet id.

Data model

In your project folder create a sub folder named database. In the database sub folder create a file named database.py. This file will be used by SQLALchemy to:

  • Define the database engine used to generate and interact with the SQLite file named database.db.
  • Create the Base class used to produce database tables and map them to their respective classes and attributes.
  • Manage the database sessions in order to execute queries against the database.

database.py

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
import os

# Create database engine
db_name = 'database.db'
db_path = os.path.join(os.path.dirname(__file__), db_name)
db_uri = 'sqlite:///{}'.format(db_path)
engine = create_engine(db_uri, convert_unicode=True)

# Declarative base model to create database tables and classes
Base = declarative_base()
Base.metadata.bind = engine  # Bind engine to metadata of the base class

# Create database session object
db_session = scoped_session(sessionmaker(bind=engine, expire_on_commit=False))
Base.query = db_session.query_property()  # Used by graphql to execute queries

In the database sub folder create two files named model_people.py and model_planet.py which will contain the data model information required by SQLAlchemy to create the tables and relationships.

model_people.py

from .database import Base
from sqlalchemy import Column, ForeignKey, Integer, String


class People(Base):
    """People model."""

    __tablename__ = 'people'

    id = Column('id', Integer, primary_key=True)
    name = Column('name', String)
    height = Column('height', Integer)
    mass = Column('mass', Integer)
    hair_color = Column('hair_color', String)
    skin_color = Column('skin_color', String)
    eye_color = Column('eye_color', String)
    birth_year = Column('birth_year', String)
    gender = Column('gender', String)
    homeworld = Column('homeworld', Integer, ForeignKey('planet.id'))
    created = Column('created', String)
    edited = Column('edited', String)
    url = Column('url', String)

model_planet.py

from .database import Base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship


class Planet(Base):
    """Planet model."""

    __tablename__ = 'planet'

    id = Column('id', Integer, primary_key=True)
    name = Column('name', String)
    rotation_period = Column('rotation_period', Integer)
    orbital_period = Column('orbital_period', Integer)
    diameter = Column('diameter', Integer)
    climate = Column('climate', String)
    gravity = Column('gravity', String)
    terrain = Column('terrain', String)
    surface_water = Column('surface_water', Integer)
    population = Column('population', Integer)
    created = Column('created', String)
    edited = Column('edited', String)
    url = Column('url', String)

    peoples = relationship('People', backref='planet')