Uncategorized

Creating API with GraphQL+Django

Environment:

Django 1.10.4
graphene-django-1.2.0

Setup

Install graphene-django,`migrate` and `createsuperuser` if it’s a new Django project:


pip install graphene-django
django-admin startproject dmyz
cd dmyz
python manage.py migrate
python manage.py createsuperuser

Edit settings.py,add `graphene-django` to `INSTALLED_APPS`:


INSTALLED_APPS = (
    # ...
    'graphene_django',
)

Then editurls.py,import `GraphQLView`:


from graphene_django.views import GraphQLView

urlpatterns = [
    # ...
    url(r'^graphql', GraphQLView.as_view(graphiql=True)),
]

Execute `runserver` then open uri /graphql, will reponse a error about schema。

Schema

Create schema.py, folder structure like blow:


dmyz
├── db.sqlite3
├── dmyz
│   ├── __init__.py
│   ├── schema.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

Edit schema.py, import `DjangoObjectType` and `graphene`. Use Django’s User Model as example:


from django.contrib.auth.models import User as UserModel

from graphene_django import DjangoObjectType
import graphene

class User(DjangoObjectType):
    class Meta:
        model = UserModel

class Query(graphene.ObjectType):
    users = graphene.List(User)

    @graphene.resolve_only_args
    def resolve_users(self):
        return UserModel.objects.all()

schema = graphene.Schema(query=Query)

Edit settings.py:


GRAPHENE = {
    'SCHEMA': 'dmyz.schema.schema'
}

Now reopen /graphql will show GraphiQL (GraphQL Web IDE), wirte then query:


{
  users {
    username
    email
  }
}

Return username and email of admin when click button (▶️). More detail query language of GraphQL see :http://graphql.org/learn/queries/

Schema & Type & Field

The query language is the same whether your backend using Python or Nodejs. Schema defines the presentation structure of the data, including various Types, where Query and Mutation are two special types, and Type specifies the returned data field through Fields. Taking the previous code as an example, Type(Query) and Fields(users) are defined in the code, and resolve is specified to process the data.

Filter

Insert a new user for testing:


python manage.py shell -c "from django.contrib.auth.models import User;User.objects.create_user(username='dmyz',email='admin@dmyz.org',password='dmyz.org')"

Editschema.py


class Query(graphene.ObjectType):
    users = graphene.List(User,
            id=graphene.Int()) #id field as query parameter

#    @graphene.resolve_only_args decorator recive args
    def resolve_users(self, args, context, info):
        if args == {}: 
            return UserModel.objects.all()
        return UserModel.objects.filter(pk=args.get('id')) 

schema = graphene.Schema(query=Query)

Run the new query lanaguage:


query userId{users(id: 2) {id,username,email}}

curl "http://127.0.0.1:8000/graphql?query=query%20userId%7Busers(id%3A%202)%20%7Bid%2Cusername%2Cemail%7D%7D&operationName=userId" | python -m json.tool

{
    "data": {
        "users": [{
            "id": "2",
            "username": "dmyz",
            "email": "admin@dmyz.org"
        }]
    }
}

Mutation

Extend `graphene.Mutation`:


class CreateUser(graphene.Mutation):
    class Input:
        username = graphene.String()
        password = graphene.String()
        email = graphene.String()
    ok = graphene.Boolean()
    user = graphene.Field(lambda: User)

    def mutate(self, args, content, info):
        user = User(username=args.get('username'))
        ok = True
        return CreateUser(ok=ok, user=user)

class Mutation(graphene.ObjectType):
    create_user = CreateUser.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

Query lanaguage declare as mutation, define fields of response:


mutation {
  createUser(username: "graphql", password: "test") {
    ok
    user {
      username
    }
  }
}

Reponse:


{
  "data": {
    "createUser": {
      "ok": true,
      "user": {
        "username": "graphql"
      }
    }
  }
}
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments