前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为 Django 配备 GraphQL API

为 Django 配备 GraphQL API

作者头像
somenzz
发布2021-07-01 17:06:53
8450
发布2021-07-01 17:06:53
举报
文章被收录于专栏:Python七号

前文再见 REST,你好 GraphQL提到,GraphQL 使得前端按需请求后端数据,前后端接口不再高度耦合,可以大大提高前后端的开发效率,从而快速进行产品迭代。Github v4 版外部 API 只使用 GraphQL,可见 GraphQL 是一个明显的趋势,值得我们去学习和使用。今天就分享一下如何为 Django 配置 GraphQL API。

先看下最终的效果:

提出问题

首先,我们先提出一个小小的需求,针对这个小小的需求,设计代码。

假如要开发一个菜谱应用,要支持原材料的录入和分类,前端需要灵活的展示某个原材料属于哪个分类,某个分类下有哪些原材料,并且可以传入参数查询。

请编码实现原材料和分类的灵活查询。

解决问题

接下来,我们创建 Django 应用解决问题。

1、先安装 django,graphene-django。graphene-django 就是为 Django 提供 GraphQL API 的三方库。

代码语言:javascript
复制
pip install django
pip install graphene-django

2、生成 Django 初始代码,编写 models.py,编写 GraphQL 的模式。

代码语言:javascript
复制
django-admin startproject cookbook
cd cookbook
python manage.py startapp ingredients

修改 models.py 文件,添加两个类,一个是对应分类,别一个对应原料,修改后内容如下所示:

代码语言:javascript
复制
from django.db import models

# Create your models here.


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

外键代表两者之间的关系:一个分类下面可以有多个原料,但一个原料只能属于某一个分类。

然后,我们在 settings.py 同一级的目录,新增一个 schema.py 文件,内容如下:

代码语言:javascript
复制
import graphene
from graphene_django import DjangoObjectType

from ingredients.models import Category, Ingredient

class CategoryType(DjangoObjectType):
    class Meta:
        model = Category
        fields = ("id", "name", "ingredients")

class IngredientType(DjangoObjectType):
    class Meta:
        model = Ingredient
        fields = ("id", "name", "notes", "category")

class Query(graphene.ObjectType):
    all_ingredients = graphene.List(IngredientType)
    all_categorys = graphene.List(CategoryType)
    category_by_name = graphene.Field(CategoryType, name=graphene.String(required=True))

    def resolve_all_categorys(root, info):
        return Category.objects.all()

    def resolve_all_ingredients(root, info):
        # We can easily optimize query count in the resolve method
        return Ingredient.objects.all()

    def resolve_category_by_name(root, info, name):
        try:
            return Category.objects.get(name=name)
        except Category.DoesNotExist:
            return None

schema = graphene.Schema(query=Query)

schema 是 GraphQL 的核心代码,Query 类和 models 类很像,对比着写代码就可以了,后面熟悉之后再理解它的原理。

接着,我们在 settings.py 的 INSTALLED_APPS 添加两条记录:

代码语言:javascript
复制
    "ingredients.apps.IngredientsConfig",
    "graphene_django",

配置 cookbook.urls 使用刚才创建的 schema, 内容如下:

代码语言:javascript
复制
from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from graphene_django.views import GraphQLView
from cookbook.schema import schema
urlpatterns = [
    path("admin/", admin.site.urls),
    path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True,schema=schema))),
]

3、建表,插入测试数据。

代码语言:javascript
复制
(py38env) ➜  cookbook python manage.py makemigrations
Migrations for 'ingredients':
  ingredients/migrations/0001_initial.py
    - Create model Category
    - Create model Ingredient
(py38env) ➜  cookbook python manage.py migrate       
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, ingredients, sessions
Running migrations:
  Applying ingredients.0001_initial... OK
(py38env) ➜  cookbook ls
cookbook    db.sqlite3  ingredients manage.py

至此,db.sqlite3 中已经有了两张表,接下来插入测试数据,数据来源:ingredients.json

下载后保存到项目的根目录,也就是第一个 cookbook 目录下,然后执行下面的命令导入测试数据:

代码语言:javascript
复制
(py38env) ➜  cookbook python manage.py loaddata ingredients.json 
Installed 6 object(s) from 1 fixture(s)

4、启动服务,并测试。

代码语言:javascript
复制
python manage.py runserver

浏览器打开 http://localhost:8000/graphql/ 就可以看到如下页面:

这就是 GraphQL 的接口调试界面,左边输入查询条件,右边返回数据。

比如查一下所有的原料表:

代码语言:javascript
复制
query {
  allIngredients {
    id
    name
    note
  }
}

查一下所有的原料表,包含对应的分类信息:

代码语言:javascript
复制
query {

 allIngredients{
    id
    name
    notes
    category{
      id
      name
    }
  }
  
}

接下来反着查一下,比如查询所有的分类:

代码语言:javascript
复制
query {
 allCategorys {
   id
    name
 }
}

查询所有的分类及对应的原料信息:

代码语言:javascript
复制
query {
 allCategorys {
   id
    name
    ingredients{
      id
      name
      notes
    }
 }
}

查询某一分类,比如乳制品分类下面的原料信息:

代码语言:javascript
复制
query {
  categoryByName(name: "Dairy") {
    id
    name
    ingredients {
      id
      name
    }
  }
}

获取源代码

如果你按上述步骤没有达到预期效果,可以获取我这里的代码对比下,公众号「Python七号」对话框回复「graphql」获取。

总结

GraphQL 非常强大,并且可以快速集成 Django 模型,从而可以非常方便的将你的应用 api 转换为 GraphQL 风格。如果你想了解更多用法,请阅读 Graphene 官方文档。

本文分享了后端用 Django 实现 GraphQL API 的 demo,下一次分享如果在前端使用 GraphQL,让 GraphQL 在前后端都跑起来。

关注「Python七号」并加星标,第一时间收到文章推送,如果你需要技术支持,请加我微信。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python七号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 提出问题
  • 解决问题
  • 获取源代码
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档