mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-18 12:30:37 +03:00
Further work on django quickstart
This commit is contained in:
parent
90f58e786a
commit
5e6f4cf302
|
@ -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. We’ll 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in New Issue
Block a user