graphene-django学习笔记(一)

一、django基础

1、建立django项目

# Create the project directory
mkdir cookbook
cd cookbook

# Create a virtualenv to isolate our package dependencies locally
virtualenv env
source env/bin/activate  # On Windows use `env\Scripts\activate`

# Install Django and Graphene with Django support
pip install django
pip install graphene_django

# Set up a new project with a single application
django-admin startproject cookbook 
cd cookbook

python manage.py startapp ingredients  

  2、同步数据库

python manage.py migrate

 3、创建models

# cookbook/ingredients/models.py
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)
    notes = models.TextField()
    category = models.ForeignKey(
        Category, related_name='ingredients', on_delete=models.CASCADE)

    def __str__(self):
        return self.name

  4、注册app

INSTALLED_APPS = [
    ...
    # Install the ingredients app
    ''ingredients.apps.IngredientsConfig',
]

  5、创建并更新数据库表

python manage.py makemigrations
python manage.py migrate

  6、加载一些数据

在cookbook/ingredients文件夹下创建文件夹fixture,创建ingredients.json文件

[{"model": "ingredients.category", "pk": 1, "fields": {"name": "Dairy"}}, {"model": "ingredients.category", "pk": 2, "fields": {"name": "Meat"}}, {"model": "ingredients.ingredient", "pk": 1, "fields": {"name": "Eggs", "notes": "Good old eggs", "category": 1}}, {"model": "ingredients.ingredient", "pk": 2, "fields": {"name": "Milk", "notes": "Comes from a cow", "category": 1}}, {"model": "ingredients.ingredient", "pk": 3, "fields": {"name": "Beef", "notes": "Much like milk, this comes from a cow", "category": 2}}, {"model": "ingredients.ingredient", "pk": 4, "fields": {"name": "Chicken", "notes": "Definitely doesn't come from a cow", "category": 2}}]

  然后使用

python mangae.py loaddata ingredients

  7、创建超级用户

python manage.py createsuperuser

  然后输入用户名,密码和邮箱

8、在admin中注册刚刚创建的model,以便于可以登录admin后台进行管理,新增或删除数据。

# cookbook/ingredients/admin.py
from django.contrib import admin
from .models import Category, Ingredient

admin.site.register(Category)
admin.site.register(Ingredient)

  

9、运行服务器

python mangae.py runserver

  默认在8000端口,然后打开localhost:8000/admin使用刚才创建的用户名和密码登录。可以看到我们刚才通过json文件加载的数据了。

二、schema 和object types

为了能够像django发送graphql请求,我们需要做下面一些事情:

(1)使用type类型系统创建Schema,

(2)创建一个view接受请求并根据schema返回结果

1、创建app层次的schema

GraphQL将您的对象作为图形结构呈现给世界,而不是您可能习惯的层次结构。为了创建这种表示,Graphene需要知道将出现在图中的每种对象的类型。这意味着我们需要为每一个model创建一个类型系统,继承DjangoObjectType.当我们定义好每个模型对应的type之后,我们可以把这些定义的类型展示在Query下。Query是graphql的一个根类型,graphql有一个还有一些根类型如Query,Mutation,Subscription等

在cookbook/ingredients下定义schema.py

import graphene
from graphene_django import DjangoObjectType

from .models import Category,Ingredient

class CategoryType(DjangoObjectType):
    class meta:
        model=Category

class IngredientType(DjangoObjectType):
    class meta:
        model=Ingredient

class Query(object):
    all_categories = graphene.List(CategoryType)
    all_Ingredients = graphene.List(IngredientType)

    def resolve_all_categories(self,info,**kwargs):
        return Category.objects.all()

    def resolve_all_ingredients(self,info,**kwargs):
        return Ingredient.objects.select_related('category').all()

  首先使用DjangoObjectType将model中的字段转换为GraphQL对应的type

  第二在Query中列示出所有的model,有两个对象分别都是一个列表Type,all_categories和all_Ingerdients。

  第三创建resolve_(字段)定义各自的解析函数。

注意这里的Query是一个mixin,我们将要在Django project层面创建一个Query,继承所有app中的Query

2、创建项目顶层的schema

在cookbook/cookbook下创建一个schema

import graphene
import ingredients.schema

class Query(cookbook.ingredients.schema.Query,graphene.ObjectType) :
    pass

schema = graphene.Schema(query=Query)

  可以把项目顶层的schema视作顶层的路由urls.py

3、注册app,时的graphql_schema可用

INSTALLED_APPS = [
    ...
    # This will also make the `graphql_schema` management command available
    'graphene_django',
]

  

4、为graphene添加schema配置文件

将顶层的schema作为入口文件

GRAPHENE = {
    'SCHEMA': 'cookbook.schema.schema'
}

  

三、创建GraphQL views

与reat api不同,graphQL只需要一个端口来发送所有的请求。

定义url,使用GraphQLView作为接口,graphiql=true默认将显示graphiql工具。

from django.contrib import admin
from django.urls import path
from graphene_django.views import GraphQLView
urlpatterns = [
    path('admin/', admin.site.urls),
    path('graphql',GraphQLView.as_view(graphiql=True))
]

  如果我们没有在Django的settings.py文件中指定schema,也可以在这里设置

from django.conf.urls import url, include
from django.contrib import admin

from graphene_django.views import GraphQLView

from cookbook.schema import schema

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^graphql', GraphQLView.as_view(graphiql=True, schema=schema)),
]

  在graphiql中输入查询

{
  allCategories{
      id
      name
      ingredients {
        id
        name
      }
    }
}

  得到结果

{
  "data": {
    "allCategories": [
      {
        "id": "1",
        "name": "Dairy",
        "ingredients": [
          {
            "id": "1",
            "name": "Eggs"
          },
          {
            "id": "2",
            "name": "Milk"
          }
        ]
      },
      {
        "id": "2",
        "name": "Meat",
        "ingredients": [
          {
            "id": "3",
            "name": "Beef"
          },
          {
            "id": "4",
            "name": "Chicken"
          }
        ]
      }
    ]
  }
}

  (1)可以看到schema这里自动转化为了驼峰标志。all_categories自动变成了allCategories

  (2)我们这里使用GraphQL可以从category查到ingredients.同时我们也可以进行反向查询,即从ingredients查询到category

四、查询单个对象

在ingredients中增加schema中增加单个对象和相关解析函数。

class Query(object):
    category = graphene.Field(CategoryType,
                              id=graphene.Int(),
                              name=graphene.String())
    all_categories = graphene.List(CategoryType)


    ingredient = graphene.Field(IngredientType,
                                id=graphene.Int(),
                                name=graphene.String())
    all_ingredients = graphene.List(IngredientType)

    def resolve_all_categories(self, info, **kwargs):
        return Category.objects.all()

    def resolve_all_ingredients(self, info, **kwargs):
        return Ingredient.objects.all()

    def resolve_category(self, info, **kwargs):
        id = kwargs.get('id')
        name = kwargs.get('name')

        if id is not None:
            return Category.objects.get(pk=id)

        if name is not None:
            return Category.objects.get(name=name)

        return None

    def resolve_ingredient(self, info, **kwargs):
        id = kwargs.get('id')
        name = kwargs.get('name')

        if id is not None:
            return Ingredient.objects.get(pk=id)

        if name is not None:
            return Ingredient.objects.get(name=name)

        return None

  

 

 

posted @ 2018-09-07 21:12  tutu_python  阅读(425)  评论(0)    收藏  举报