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): class Category(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Ingredient(models.Model): class Ingredient(models.Model):
name = models.CharField(max_length=100) 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 ## Schema
@ -51,84 +58,179 @@ Create `cookbook/ingredients/schema.py` and type the following:
```python ```python
# cookbook/ingredients/schema.py # cookbook/ingredients/schema.py
import graphene from graphene import relay, ObjectType
from graphene.contrib.django import DjangoObjectType 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. # 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) # This is configured in the UserType's Meta class (as you can see below)
class UserType(DjangoObjectType): class CategoryNode(DjangoNode):
class Meta: class Meta:
model = User model = Category
only_fields = ('username', 'email', 'groups') filter_fields = ['name', 'ingredients']
class GroupType(DjangoObjectType): class IngredientNode(DjangoNode):
class Meta: class Meta:
model = Group model = Ingredient
only_fields = ('name', ) filter_fields = ['name', 'notes', 'category']
class Query(graphene.ObjectType): class Query(ObjectType):
get_user = graphene.Field(UserType, category = relay.NodeField(CategoryNode)
id=graphene.String().NonNull) all_categories = DjangoFilterConnectionField(CategoryNode)
get_group = graphene.Field(GroupType,
id=graphene.String().NonNull)
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 ## 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 ```python
INSTALLED_APPS = [ INSTALLED_APPS = [
# The other installed apps ...
'django_graphiql', 'django_graphiql',
] ]
``` ```
## Creating GraphQL and GraphiQL views ## 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. Requests to this URL are handled by Graphene's `GraphQLView` view.
Additionally, an interface for navigating this API will be very useful. Graphene Additionally, we'll add a URL for aforementioned GraphiQL, and for the Django admin
includes the [graphiql](https://github.com/graphql/graphiql) in-browser IDE interface (the latter can be useful for creating test data).
which assists in exploring and querying your new API. Well add a URL for this too.
```python ```python
from django.conf.urls import url, include from django.conf.urls import url, include
from django.contrib import admin
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from graphene.contrib.django.views import GraphQLView 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 = [ urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))), url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))),
url(r'^graphiql', include('django_graphiql.urls')), 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 ## 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. We're now ready to test the API we've built. Let's fire up the server from the command line.
```bash ```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 ```graphql
myQuery { query {
getUser(id:"1") { allIngredients {
username 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
}
}
}
}
}
}
} }
``` ```