Further work on django quickstart

This commit is contained in:
Adam Charnock 2015-12-29 14:18:32 +00:00
parent 90f58e786a
commit 5e6f4cf302

View File

@ -30,10 +30,17 @@ from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category)
notes = models.TextField()
category = models.ForeignKey(Category, related_name='ingredients')
def __str__(self):
return self.name
```
## Schema
@ -51,84 +58,179 @@ Create `cookbook/ingredients/schema.py` and type the following:
```python
# cookbook/ingredients/schema.py
import graphene
from graphene.contrib.django import DjangoObjectType
from graphene import relay, ObjectType
from graphene.contrib.django.filter import DjangoFilterConnectionField
from graphene.contrib.django.types import DjangoNode
from cookbook.ingredients.models import Category, Ingredient
from django.contrib.auth.models import User, Group
# Graphene will automatically map the User model's fields onto the UserType.
# This is configured in the UserType's Meta class (as you can see below)
class UserType(DjangoObjectType):
class CategoryNode(DjangoNode):
class Meta:
model = User
only_fields = ('username', 'email', 'groups')
model = Category
filter_fields = ['name', 'ingredients']
class GroupType(DjangoObjectType):
class IngredientNode(DjangoNode):
class Meta:
model = Group
only_fields = ('name', )
model = Ingredient
filter_fields = ['name', 'notes', 'category']
class Query(graphene.ObjectType):
get_user = graphene.Field(UserType,
id=graphene.String().NonNull)
get_group = graphene.Field(GroupType,
id=graphene.String().NonNull)
class Query(ObjectType):
category = relay.NodeField(CategoryNode)
all_categories = DjangoFilterConnectionField(CategoryNode)
schema = graphene.Schema(query=Query)
ingredient = relay.NodeField(IngredientNode)
all_ingredients = DjangoFilterConnectionField(IngredientNode)
class Meta:
abstract = True
```
Note that the above `Query` class is marked as 'abstract'. This is because we
want will now create a project-level query which will combine all our app-level
queries.
Create the parent project-level `cookbook/schema.py`:
```python
import graphene
import cookbook.ingredients.schema
class Query(cookbook.ingredients.schema.Query):
# This class will inherit from multiple Queries
# as we begin to add more apps to our project
pass
schema = graphene.Schema(name='Cookbook Schema')
schema.query = Query
```
You can think of this as being something like your top-level `urls.py`
file (although it currently lacks any namespacing).
## Adding GraphiQL
For having the GraphiQL static assets we need to append `django_graphiql` in `INSTALLED_APPS` in `tutorial/settings.py`:
GraphiQL is a web-based integrated development environment to assist in the
writing and executing of GraphQL queries. It will provide us with a simple
and easy way of testing our cookbook project.
Add `django_graphiql` to `INSTALLED_APPS` in `cookbook/settings.py`:
```python
INSTALLED_APPS = [
# The other installed apps
...
'django_graphiql',
]
```
## Creating GraphQL and GraphiQL views
Unlike a RESTful API, there is only a single URL from which a GraphQL is accessed.
Unlike a RESTful API, there is only a single URL from which GraphQL is accessed.
Requests to this URL are handled by Graphene's `GraphQLView` view.
Additionally, an interface for navigating this API will be very useful. Graphene
includes the [graphiql](https://github.com/graphql/graphiql) in-browser IDE
which assists in exploring and querying your new API. Well add a URL for this too.
Additionally, we'll add a URL for aforementioned GraphiQL, and for the Django admin
interface (the latter can be useful for creating test data).
```python
from django.conf.urls import url, include
from django.contrib import admin
from django.views.decorators.csrf import csrf_exempt
from graphene.contrib.django.views import GraphQLView
from quickstart.schema import schema
from cookbook.schema import schema
# Wire up our GraphQL schema to /graphql.
# Additionally, we include GraphiQL view for querying easily our schema.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))),
url(r'^graphiql', include('django_graphiql.urls')),
]
```
## Load some test data
**TODO:** Insert link to fixture
Now is a good time to load up some test data. The easiest option will be to download
the ingredients.json fixture and place it in
`cookbook/ingredients/fixtures/ingredients.json`. You can then run the following:
```
$ python ./manage.py loaddata ingredients
Installed 6 object(s) from 1 fixture(s)
```
Alternatively you can use the Django admin interface to create some data youself.
You'll need to run the development server (see below), and probably create a login
for yourself too (`./manage.py createsuperuser`).
## Testing our GraphQL schema
We're now ready to test the API we've built. Let's fire up the server from the command line.
```bash
python ./manage.py runserver
$ python ./manage.py runserver
Performing system checks...
Django version 1.9, using settings 'cookbook.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
Go to [localhost:8080/graphiql](http://localhost:8080/graphiql) and type your first query!
Go to [localhost:8000/graphiql](http://localhost:8000/graphiql) and type your first query!
```graphql
myQuery {
getUser(id:"1") {
username
query {
allIngredients {
edges {
node {
id,
name
}
}
}
}
```
The above will return the names & IDs for all ingredients. But perhaps you want
a specific ingredient:
```graphql
query {
# Graphene creates globally unique IDs for all objects.
# You may need to copy this value from the results of the first query
ingredient(id: "SW5ncmVkaWVudE5vZGU6MQ==") {
name
}
}
```
You can also get each ingredient for each category:
```graphql
query {
allCategories {
edges {
node {
name,
ingredients {
edges {
node {
name
}
}
}
}
}
}
}
```