如何在Django中使用GraphQL

546 阅读3分钟

如何在Django中使用GraphQL

GraphQL是未来的趋势吗?

GraphQL是一种用于API的查询语言,使客户能够准确地从API中提出他们所需要的东西。在这篇文章中,我们将探讨GraphQL以及如何在Django (Python网络框架)中使用它。让我们来参观一下。

安装

$ pip install Django$ pip install graphene-django

设置Django项目

我们需要创建我们的Django项目。

  • 一个名为Django的项目bookstore
  • bookstore 内的一个应用程序,名为books
$ django-admin startproject bookstore
$ cd bookstore
$ django-admin startapp books

settings.py我们需要在我们的Django项目的graphene_djangobookstore.books中添加INSTALLED_APPS

INSTALLED_APPS = [
    #...
    'django.contrib.staticfiles',
    'graphene_django'
    'bookstore.books'
]

定义我们的模型

一个模型是关于我们数据的单一的、确定的信息来源。每个模型都映射到一个单一的数据库表。我们将使用一个SQLite数据库,用于在线书店的库存和销售database/bookstore.db

from django.db import models
#...
class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    p_name = models.CharField(max_length=40)
    city = models.CharField(max_length=20)
    zip = models.CharField(max_length=10)
class Meta:
    managed = False
    db_table = 'Publisher'

class Book(models.Model):
    id = models.CharField(max_length=20, primary_key=True)
    pub = models.ForeignKey('Publisher', models.DO_NOTHING)
    title = models.CharField(max_length=100)
    price = models.FloatField()
    category = models.CharField(max_length=30, null=True)
    quantity = models.IntegerField()
    b_format = models.CharField(max_length=40, null=True)
    prod_year = models.IntegerField()
    filesize = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'Book'
  • 在你的Django项目的urls.py ,添加一个graphql URL。
from django.urls import path
from graphene_django.views import GraphQLView

urlpatterns = [
    #...
    path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
]

CSRF中间件和模板标签提供了易于使用的保护,防止跨站请求伪造

  • 在我们的Django项目设置中定义Graphene的模式位置。
GRAPHENE = {    'SCHEMA': 'bookstore.books.schema'}

为了进行GraphQL查询,我们需要.NET Framework。

  • 带有定义对象类型的模式。
  • 一个视图,将查询作为输入并返回结果。

模式books/schema.py 应该包括两个名为QueryMutation 的类,这些类扩展了你应用程序中的所有模式。

查询

查询是发送到服务器的字符串,被解释和执行,然后它们返回JSON数据给客户端。这里我们有一个查询,它将返回存储在数据库中的所有书籍和出版商的列表。

import graphene
from graphene import ObjectType, Schema, Mutationfrom graphene_django import DjangoObjectType
from bookstore.books.models import Publisher, Book
class PublisherType(DjangoObjectType):
    class Meta:
        model  = Publisher
        fields = ("id", "p_name", "city", "zip")
class BookType(DjangoObjectType):
    class Meta:
    model  = Book
    fields = ("id", "pub", "title", "price", "category", "quantity", "b_format", "prod_year", "filesize")
class Query(ObjectType):
    all_book      = graphene.List(BookType)
    all_publisher = graphene.List(PublisherType)

解析器

为了响应查询,一个模式需要有所有字段的解析器。解析器是一个函数的集合,它为GraphQL查询生成响应。

#...
@graphene.resolve_only_args
    def resolve_all_book(self):
        return Book.objects.all()
@graphene.resolve_only_args
    def resolve_all_publisher(self):
        return Publisher.objects.all()

变异

大多数关于GraphQL的讨论都集中在数据获取上,但任何完整的数据平台都需要一种方法来修改服务器端的数据。突变查询修改数据存储中的数据并返回一个值。

class CreatePublisher(Mutation):
    id     = graphene.String()
    p_name = graphene.String()
    city   = graphene.String()
    zip    = graphene.String()
    class Arguments:
        id = graphene.NonNull(graphene.Int)
        p_name = graphene.String()
        city   = graphene.String()
        zip    = graphene.String()
    def mutate(self, info, id, p_name, city, zip):
        publisher = Publisher(id=id, p_name=p_name, city=city, zip=zip)
        publisher.save()
        return CreatePublisher(id     = publisher.id,
                               p_name = publisher.p_name,
                               city   = publisher.city,
                               zip    = publisher.zip,
        )
class Mutation(graphene.ObjectType):
    create_publisher = CreatePublisher.Field()

GraphQL vs. REST API

GraphQL和REST API的主要区别在于,GraphQL是一种规范,一种查询语言,而REST是基于网络的软件的架构概念。

一个REST请求是由endpointHTTP methodHeaderBody 。对于调用REST API,我们一般使用HTTP方法,如POSTGETPUTDELETE ,而另一方面,GraphQL使用不同的方法,称为查询变异

总结

GraphQL很好,它是强类型的,基于模式类型和描述的自我记录,并与代码生成器工具集成以减少开发时间。