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"
}
}
}
}