@@ -30,10 +30,17 @@ from django.db import models
30
30
class Category (models .Model ):
31
31
name = models.CharField(max_length = 100 )
32
32
33
+ def __str__ (self ):
34
+ return self .name
35
+
33
36
34
37
class Ingredient (models .Model ):
35
38
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
37
44
```
38
45
39
46
## Schema
@@ -51,84 +58,179 @@ Create `cookbook/ingredients/schema.py` and type the following:
51
58
52
59
``` python
53
60
# 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
56
66
57
- from django.contrib.auth.models import User, Group
58
67
59
68
# Graphene will automatically map the User model's fields onto the UserType.
60
69
# This is configured in the UserType's Meta class (as you can see below)
61
- class UserType ( DjangoObjectType ):
70
+ class CategoryNode ( DjangoNode ):
62
71
class Meta :
63
- model = User
64
- only_fields = ( ' username ' , ' email ' , ' groups ' )
72
+ model = Category
73
+ filter_fields = [ ' name ' , ' ingredients ' ]
65
74
66
75
67
- class GroupType ( DjangoObjectType ):
76
+ class IngredientNode ( DjangoNode ):
68
77
class Meta :
69
- model = Group
70
- only_fields = (' name' , )
78
+ model = Ingredient
79
+ filter_fields = [' name' , ' notes' , ' category' ]
80
+
71
81
82
+ class Query (ObjectType ):
83
+ category = relay.NodeField(CategoryNode)
84
+ all_categories = DjangoFilterConnectionField(CategoryNode)
72
85
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)
78
88
79
- schema = graphene.Schema(query = Query)
89
+ class Meta :
90
+ abstract = True
80
91
```
81
92
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).
82
116
83
117
## Adding GraphiQL
84
118
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 ` :
86
124
87
125
``` python
88
126
INSTALLED_APPS = [
89
- # The other installed apps
127
+ ...
90
128
' django_graphiql' ,
91
129
]
92
130
```
93
131
94
132
## Creating GraphQL and GraphiQL views
95
133
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.
97
135
Requests to this URL are handled by Graphene's ` GraphQLView ` view.
98
136
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).
102
139
103
140
``` python
104
141
from django.conf.urls import url, include
142
+ from django.contrib import admin
105
143
from django.views.decorators.csrf import csrf_exempt
144
+
106
145
from graphene.contrib.django.views import GraphQLView
107
- from quickstart.schema import schema
108
146
147
+ from cookbook.schema import schema
109
148
110
- # Wire up our GraphQL schema to /graphql.
111
- # Additionally, we include GraphiQL view for querying easily our schema.
112
149
urlpatterns = [
150
+ url(r ' ^ admin/' , admin.site.urls),
113
151
url(r ' ^ graphql' , csrf_exempt(GraphQLView.as_view(schema = schema))),
114
152
url(r ' ^ graphiql' , include(' django_graphiql.urls' )),
115
153
]
116
154
```
117
155
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
+
118
174
## Testing our GraphQL schema
119
175
120
176
We're now ready to test the API we've built. Let's fire up the server from the command line.
121
177
122
178
``` 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
+ }
124
213
```
125
214
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:
127
216
128
217
``` 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
+ }
132
233
}
234
+ }
133
235
}
134
236
```
0 commit comments