Graphene-Python (original) (raw)
SQLAlchemy + Flask Tutorial¶
Graphene comes with builtin support to SQLAlchemy, which makes quite easy to operate with your current models.
Note: The code in this tutorial is pulled from the Flask SQLAlchemy example app.
Setup the Project¶
We will setup the project, execute the following:
Create the project directory
mkdir flask_sqlalchemy cd flask_sqlalchemy
Create a virtualenv to isolate our package dependencies locally
virtualenv env
source env/bin/activate # On Windows use env\Scripts\activate
SQLAlchemy and Graphene with SQLAlchemy support
pip install SQLAlchemy pip install graphene_sqlalchemy
Install Flask and GraphQL Flask for exposing the schema through HTTP
pip install Flask pip install Flask-GraphQL
Defining our models¶
Let’s get started with these models:
flask_sqlalchemy/models.py
from sqlalchemy import * from sqlalchemy.orm import (scoped_session, sessionmaker, relationship, backref) from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True) db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base = declarative_base()
We will need this for querying
Base.query = db_session.query_property()
class Department(Base): tablename = 'department' id = Column(Integer, primary_key=True) name = Column(String)
class Employee(Base): tablename = 'employee' id = Column(Integer, primary_key=True) name = Column(String) hired_on = Column(DateTime, default=func.now()) department_id = Column(Integer, ForeignKey('department.id')) department = relationship( Department, backref=backref('employees', uselist=True, cascade='delete,all'))
Schema¶
GraphQL presents your objects to the world as a graph structure rather than a more hierarchical structure to which you may be accustomed. In order to create this representation, Graphene needs to know about each_type_ of object which will appear in the graph.
This graph also has a root type through which all access begins. This is the Query
class below. In this example, we provide the ability to list all employees via all_employees
, and the ability to obtain a specific node via node
.
Create flask_sqlalchemy/schema.py
and type the following:
flask_sqlalchemy/schema.py
import graphene from graphene import relay from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField from .models import db_session, Department as DepartmentModel, Employee as EmployeeModel
class Department(SQLAlchemyObjectType): class Meta: model = DepartmentModel interfaces = (relay.Node, )
class Employee(SQLAlchemyObjectType): class Meta: model = EmployeeModel interfaces = (relay.Node, )
class Query(graphene.ObjectType): node = relay.Node.Field() # Allows sorting over multiple columns, by default over the primary key all_employees = SQLAlchemyConnectionField(Employee.connection) # Disable sorting over this field all_departments = SQLAlchemyConnectionField(Department.connection, sort=None)
schema = graphene.Schema(query=Query)
Creating GraphQL and GraphiQL views in Flask¶
Unlike a RESTful API, there is only a single URL from which GraphQL is accessed.
We are going to use Flask to create a server that expose the GraphQL schema under /graphql
and a interface for querying it easily: GraphiQL (also under /graphql
when accessed by a browser).
Fortunately for us, the library Flask-GraphQL
that we previously installed makes this task quite easy.
flask_sqlalchemy/app.py
from flask import Flask from flask_graphql import GraphQLView
from .models import db_session from .schema import schema, Department
app = Flask(name) app.debug = True
app.add_url_rule( '/graphql', view_func=GraphQLView.as_view( 'graphql', schema=schema, graphiql=True # for having the GraphiQL interface ) )
@app.teardown_appcontext def shutdown_session(exception=None): db_session.remove()
if name == 'main': app.run()
Creating some data¶
$ python
from .models import engine, db_session, Base, Department, Employee Base.metadata.create_all(bind=engine)
Fill the tables with some data
engineering = Department(name='Engineering') db_session.add(engineering) hr = Department(name='Human Resources') db_session.add(hr)
peter = Employee(name='Peter', department=engineering) db_session.add(peter) roy = Employee(name='Roy', department=engineering) db_session.add(roy) tracy = Employee(name='Tracy', department=hr) db_session.add(tracy) db_session.commit()
Testing our GraphQL schema¶
We’re now ready to test the API we’ve built. Let’s fire up the server from the command line.
$ python ./app.py
- Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Go to localhost:5000/graphql and type your first query!
{ allEmployees { edges { node { id name department { name } } } } }