Skip to content

Commit 5e6f4cf

Browse files
author
Adam Charnock
committed
Further work on django quickstart
1 parent 90f58e7 commit 5e6f4cf

File tree

1 file changed

+132
-30
lines changed

1 file changed

+132
-30
lines changed

docs/pages/docs/quickstart-django.md

Lines changed: 132 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,17 @@ from django.db import models
3030
class Category(models.Model):
3131
name = models.CharField(max_length=100)
3232

33+
def __str__(self):
34+
return self.name
35+
3336

3437
class Ingredient(models.Model):
3538
name = models.CharField(max_length=100)
36-
category = models.ForeignKey(Category)
39+
notes = models.TextField()
40+
category = models.ForeignKey(Category, related_name='ingredients')
41+
42+
def __str__(self):
43+
return self.name
3744
```
3845

3946
## Schema
@@ -51,84 +58,179 @@ Create `cookbook/ingredients/schema.py` and type the following:
5158

5259
```python
5360
# cookbook/ingredients/schema.py
54-
import graphene
55-
from graphene.contrib.django import DjangoObjectType
61+
from graphene import relay, ObjectType
62+
from graphene.contrib.django.filter import DjangoFilterConnectionField
63+
from graphene.contrib.django.types import DjangoNode
64+
65+
from cookbook.ingredients.models import Category, Ingredient
5666

57-
from django.contrib.auth.models import User, Group
5867

5968
# Graphene will automatically map the User model's fields onto the UserType.
6069
# This is configured in the UserType's Meta class (as you can see below)
61-
class UserType(DjangoObjectType):
70+
class CategoryNode(DjangoNode):
6271
class Meta:
63-
model = User
64-
only_fields = ('username', 'email', 'groups')
72+
model = Category
73+
filter_fields = ['name', 'ingredients']
6574

6675

67-
class GroupType(DjangoObjectType):
76+
class IngredientNode(DjangoNode):
6877
class Meta:
69-
model = Group
70-
only_fields = ('name', )
78+
model = Ingredient
79+
filter_fields = ['name', 'notes', 'category']
80+
7181

82+
class Query(ObjectType):
83+
category = relay.NodeField(CategoryNode)
84+
all_categories = DjangoFilterConnectionField(CategoryNode)
7285

73-
class Query(graphene.ObjectType):
74-
get_user = graphene.Field(UserType,
75-
id=graphene.String().NonNull)
76-
get_group = graphene.Field(GroupType,
77-
id=graphene.String().NonNull)
86+
ingredient = relay.NodeField(IngredientNode)
87+
all_ingredients = DjangoFilterConnectionField(IngredientNode)
7888

79-
schema = graphene.Schema(query=Query)
89+
class Meta:
90+
abstract = True
8091
```
8192

93+
Note that the above `Query` class is marked as 'abstract'. This is because we
94+
want will now create a project-level query which will combine all our app-level
95+
queries.
96+
97+
Create the parent project-level `cookbook/schema.py`:
98+
99+
```python
100+
import graphene
101+
102+
import cookbook.ingredients.schema
103+
104+
105+
class Query(cookbook.ingredients.schema.Query):
106+
# This class will inherit from multiple Queries
107+
# as we begin to add more apps to our project
108+
pass
109+
110+
schema = graphene.Schema(name='Cookbook Schema')
111+
schema.query = Query
112+
```
113+
114+
You can think of this as being something like your top-level `urls.py`
115+
file (although it currently lacks any namespacing).
82116

83117
## Adding GraphiQL
84118

85-
For having the GraphiQL static assets we need to append `django_graphiql` in `INSTALLED_APPS` in `tutorial/settings.py`:
119+
GraphiQL is a web-based integrated development environment to assist in the
120+
writing and executing of GraphQL queries. It will provide us with a simple
121+
and easy way of testing our cookbook project.
122+
123+
Add `django_graphiql` to `INSTALLED_APPS` in `cookbook/settings.py`:
86124

87125
```python
88126
INSTALLED_APPS = [
89-
# The other installed apps
127+
...
90128
'django_graphiql',
91129
]
92130
```
93131

94132
## Creating GraphQL and GraphiQL views
95133

96-
Unlike a RESTful API, there is only a single URL from which a GraphQL is accessed.
134+
Unlike a RESTful API, there is only a single URL from which GraphQL is accessed.
97135
Requests to this URL are handled by Graphene's `GraphQLView` view.
98136

99-
Additionally, an interface for navigating this API will be very useful. Graphene
100-
includes the [graphiql](https://github.com/graphql/graphiql) in-browser IDE
101-
which assists in exploring and querying your new API. We’ll add a URL for this too.
137+
Additionally, we'll add a URL for aforementioned GraphiQL, and for the Django admin
138+
interface (the latter can be useful for creating test data).
102139

103140
```python
104141
from django.conf.urls import url, include
142+
from django.contrib import admin
105143
from django.views.decorators.csrf import csrf_exempt
144+
106145
from graphene.contrib.django.views import GraphQLView
107-
from quickstart.schema import schema
108146

147+
from cookbook.schema import schema
109148

110-
# Wire up our GraphQL schema to /graphql.
111-
# Additionally, we include GraphiQL view for querying easily our schema.
112149
urlpatterns = [
150+
url(r'^admin/', admin.site.urls),
113151
url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))),
114152
url(r'^graphiql', include('django_graphiql.urls')),
115153
]
116154
```
117155

156+
## Load some test data
157+
158+
**TODO:** Insert link to fixture
159+
160+
Now is a good time to load up some test data. The easiest option will be to download
161+
the ingredients.json fixture and place it in
162+
`cookbook/ingredients/fixtures/ingredients.json`. You can then run the following:
163+
164+
```
165+
$ python ./manage.py loaddata ingredients
166+
167+
Installed 6 object(s) from 1 fixture(s)
168+
```
169+
170+
Alternatively you can use the Django admin interface to create some data youself.
171+
You'll need to run the development server (see below), and probably create a login
172+
for yourself too (`./manage.py createsuperuser`).
173+
118174
## Testing our GraphQL schema
119175

120176
We're now ready to test the API we've built. Let's fire up the server from the command line.
121177

122178
```bash
123-
python ./manage.py runserver
179+
$ python ./manage.py runserver
180+
181+
Performing system checks...
182+
Django version 1.9, using settings 'cookbook.settings'
183+
Starting development server at http://127.0.0.1:8000/
184+
Quit the server with CONTROL-C.
185+
```
186+
187+
Go to [localhost:8000/graphiql](http://localhost:8000/graphiql) and type your first query!
188+
189+
```graphql
190+
query {
191+
allIngredients {
192+
edges {
193+
node {
194+
id,
195+
name
196+
}
197+
}
198+
}
199+
}
200+
```
201+
202+
The above will return the names & IDs for all ingredients. But perhaps you want
203+
a specific ingredient:
204+
205+
```graphql
206+
query {
207+
# Graphene creates globally unique IDs for all objects.
208+
# You may need to copy this value from the results of the first query
209+
ingredient(id: "SW5ncmVkaWVudE5vZGU6MQ==") {
210+
name
211+
}
212+
}
124213
```
125214

126-
Go to [localhost:8080/graphiql](http://localhost:8080/graphiql) and type your first query!
215+
You can also get each ingredient for each category:
127216

128217
```graphql
129-
myQuery {
130-
getUser(id:"1") {
131-
username
218+
query {
219+
allCategories {
220+
edges {
221+
node {
222+
name,
223+
224+
ingredients {
225+
edges {
226+
node {
227+
name
228+
}
229+
}
230+
}
231+
232+
}
132233
}
234+
}
133235
}
134236
```

0 commit comments

Comments
 (0)