mirror of
https://github.com/graphql-python/graphene.git
synced 2025-03-12 16:05:47 +03:00
200 lines
5.1 KiB
Markdown
200 lines
5.1 KiB
Markdown
---
|
|
title: Tutorial
|
|
description: Using SQLAlchemy with Graphene
|
|
---
|
|
|
|
# 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](https://github.com/graphql-python/graphene/tree/master/examples/flask_sqlalchemy)**.
|
|
|
|
|
|
## Setup the Project
|
|
|
|
We will setup the project, execute the following:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```python
|
|
# 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:
|
|
|
|
```python
|
|
# flask_sqlalchemy/schema.py
|
|
import graphene
|
|
from graphene import relay
|
|
from graphene.contrib.sqlalchemy import SQLAlchemyNode, SQLAlchemyConnectionField
|
|
from models import db_session, Department as DepartmentModel, Employee as EmployeeModel
|
|
|
|
schema = graphene.Schema()
|
|
|
|
|
|
@schema.register
|
|
class Department(SQLAlchemyNode):
|
|
class Meta:
|
|
model = DepartmentModel
|
|
|
|
|
|
@schema.register
|
|
class Employee(SQLAlchemyNode):
|
|
class Meta:
|
|
model = EmployeeModel
|
|
|
|
|
|
class Query(graphene.ObjectType):
|
|
node = relay.NodeField()
|
|
all_employees = SQLAlchemyConnectionField(Employee)
|
|
|
|
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 under `/graphiql`.
|
|
|
|
Fortunately for us, the library `Flask-GraphQL` that we previously installed makes this task quite easy.
|
|
|
|
```python
|
|
# flask_sqlalchemy/app.py
|
|
from flask import Flask
|
|
from flask_graphql import GraphQL
|
|
|
|
from models import db_session
|
|
from schema import schema, Department
|
|
|
|
app = Flask(__name__)
|
|
app.debug = True
|
|
|
|
# This is creating the `/graphql` and `/graphiql` endpoints
|
|
GraphQL(app, schema=schema)
|
|
|
|
@app.teardown_appcontext
|
|
def shutdown_session(exception=None):
|
|
db_session.remove()
|
|
|
|
if __name__ == '__main__':
|
|
app.run()
|
|
```
|
|
|
|
|
|
## Creating some data
|
|
|
|
```bash
|
|
$ 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.
|
|
|
|
```bash
|
|
$ python ./app.py
|
|
|
|
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
```
|
|
|
|
Go to [localhost:5000/graphiql](http://localhost:5000/graphiql) and type your first query!
|
|
|
|
```graphql
|
|
{
|
|
allEmployees {
|
|
edges {
|
|
node {
|
|
id
|
|
name
|
|
department {
|
|
name
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|