Creating a GraphQL API with Python, Graphene, and Postgres
Here are my notes on creating a GraphQL API with Python, Django, Graphene, and Postgres. I learned almost everything from the excellent GraphQL Python tutorial at howtographql.com. Optimistically, I'll write a series of posts about how to make a React Native app that no one will use. Realistically, I won't.
Contents¶
- Install Python
- Create project directory and virtualenv
- Install Django and create a Django project
- Run Postgres in Docker
- Create a database
- Configure Django to use Postgres
- Install and configure Graphene
- Create a new Django app and add a model
- GraphQL all the things
- Try it using the GraphiQL explorer
- References / See also
Install Python 3.7.2¶
$ brew install python
Create project directory and virtualenv¶
$ # make project directory
$ mkdir travelog-api
$ cd travelog-api
$ # make virtualenv
$ python3 -m venv venv
$ # activate virtualenv
$ source venv/bin/activate
$ # upgrade pip
$ pip install --upgrade pip
Install Django and create a Django project¶
(Still in the travelog-api
directory with virtualenv activated)
- Install Django 2.1.7:
$ pip install Django
- Create Django project:
$ django-admin startproject travelog_api ./
- Run migrations and run the server:
$ ./manage.py migrate $ ./manage.py runserver $ # go to http://localhost:8000 in the browser
Run Postgres in Docker¶
(Still in the travelog-api
directory with virtualenv activated)
- Install Docker for Mac
- Create a new file,
travelog-api/docker-compose.yml
:version: "3.7" services: db: image: "postgres:11.2" container_name: "travelog_postgres1" ports: - "54321:5432" volumes: - postgres_data1:/var/lib/postgresql/data volumes: postgres_data1: name: travelog_postgres_data1
- Start Postgres
$ docker-compose up -d $ docker-compose logs
Create a database¶
- Start psql:
$ docker exec -it travelog_postgres1 psql -U postgres
- Create a database (be sure to include the semicolon):
postgres=# create database travelog;
- Create user:
postgres=# create user traveloguser with password 'mypassword'; postgres=# grant all privileges on database travelog to traveloguser;
- Exit psql:
postgres=# \q
Configure Django to use Postgres¶
(Still in the travelog-api
directory with virtualenv activated)
- Install
psycopg2
2.7.7:$ pip install psycopg2-binary
- Edit
travelog-api/travelog_api/settings.py
:DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "travelog", "USER": "traveloguser", "PASSWORD": "mypassword, "HOST": "localhost", "PORT": "54321", } }
- Run database migrations and run the server:
$ ./manage.py migrate $ ./manage.py runserver $ # go to http://localhost:8000 in the browser
Install and configure Graphene¶
(Still in the travelog-api
directory with virtualenv activated)
- Install graphene-django 2.2.0
$ pip install graphene-django
- Edit the
INSTALLED_APPS
setting intravelog-api/travelog_api/settings.py
:INSTALLED_APPS = ( # After the default packages "graphene_django", )
Create a new Django app and add a model¶
(Still in the travelog-api
directory with virtualenv activated)
- Create a new Django app:
$ ./manage.py startapp geo
- Edit
travelog_api/settings.py
:INSTALLED_APPS = ( # After the default packages 'graphene_django', 'geo', )
- Edit
travelog-api/geo/models.py
:from django.db.models import DateTimeField, FloatField, Model, TextField class Location(Model): created_at = DateTimeField(auto_now_add=True) lat = FloatField() lon = FloatField() name = TextField(blank=True) updated_at = DateTimeField(auto_now=True)
- Make and run migrations:
$ ./manage.py makemigrations $ ./manage.py migrate
GraphQL all the things¶
(Still in the travelog-api
directory with virtualenv activated)
- Create a new file
travelog-api/geo/schema.py
:import graphene from graphene_django.types import DjangoObjectType from .models import Location class LocationType(DjangoObjectType): class Meta: model = Location class Query(object): all_locations = graphene.List(LocationType) def resolve_all_locations(self, info, **kwargs): return Location.objects.all() class CreateLocation(graphene.Mutation): location = graphene.Field(LocationType) class Arguments: lat = graphene.Float() lon = graphene.Float() name = graphene.String() def mutate(self, info, lat, lon, name): loc = Location(lat=lat, lon=lon, name=name) loc.save() return CreateLocation(location=loc) class Mutation(graphene.ObjectType): create_location = CreateLocation.Field()
- Create a new file
travelog-api/travelog_api/schema.py
:import graphene import geo.schema class Query(geo.schema.Query, graphene.ObjectType): pass class Mutation(geo.schema.Mutation, graphene.ObjectType): pass schema = graphene.Schema(query=Query, mutation=Mutation)
- Edit
travelog-api/travelog_api/urls.py
:from django.contrib import admin from django.urls import path from graphene_django.views import GraphQLView from .schema import schema urlpatterns = [ path("admin/", admin.site.urls), path("graphql/", GraphQLView.as_view(graphiql=True, schema=schema)), ]
Try it using the GraphiQL explorer¶
(Still in the travelog-api
directory with virtualenv activated)
- Run the server:
$ ./manage.py runserver
- Go to http://localhost:8000/graphql/ and you should see the GraphiQL interactive GraphQL explorer.
- Create a location. Enter this mutation in the left pane and hit CTRL+ENTER:
mutation { createLocation(name: "my first location", lat: 1, lon: 2) { location { id } } }
See the response:{ "data": { "createLocation": { "location": { "id": "1" } } } }
- Query all locations:
query { allLocations { createdAt id lat lon name } }
See the response:{ "data": { "allLocations": [ { "createdAt": "2019-02-22T06:39:08.512197+00:00", "id": "1", "lat": 1, "lon": 2, "name": "my first location" } ] } }
References / See also¶
- graphql-python Tutorial - How to GraphQL
- Graphene documentation
- Graphene-Django documentation
- https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-django-application-on-ubuntu-14-04
- https://www.postgresql.org/docs/11/static/sql-createuser.html
- https://www.postgresql.org/docs/10/static/sql-createrole.html
- https://hub.docker.com/_/postgres/
- How to run PostgreSQL in Docker on Mac (for local development)
- Docker cheat sheet