如何将GraphQL API整合到Django应用程序中

147 阅读8分钟

将GraphQL API集成到Django应用程序中

GraphQL是一种开源的查询语言,用于在客户端和服务器之间进行数据通信。正如GraphQL文档中所解释的那样,"GraphQL是一种用于API的查询语言,也是一种用于用你现有的数据完成这些查询的运行时间......"

简介

GraphQL由Facebook在2012年创建,为应用程序接口(API)提供了一个运行环境,它易于使用,速度快,对开发者友好。随着时间的推移,GraphQL已经被微软、GitHub、Shopify、亚马逊等公司广泛使用。

GraphQL最突出的属性是,它只需一个请求就能从多个来源返回所请求的数据,这使得它比RESTAPI更受欢迎,而RESTAPI是另一种选择。

从本质上讲,客户端可以在响应中只请求他们需要的数据,这意味着你可以完全控制数据结构,并且在一个请求中,你可以访问大量的服务。GraphQL有很多优点,但是,GraphQL的特点不在本教程的范围之内。

在本教程中,我们的重点是将GraphQL API集成到Django项目中,并有效地使用它来查询数据。

前提条件

要继续学习本教程,你应该具备以下条件。

  • 有[Python]的基本知识。
  • 对[Django]有良好的理解。

项目设置

我们将创建一个电子商务目录项目。让我们首先在终端为这个项目创建一个目录。

在你的终端上添加以下内容。

mkdir ecommerce
cd ecommerce

设置一个虚拟环境

我们将为这个项目设置一个虚拟环境。虚拟环境有助于安装软件包,通过为不同的项目创建隔离的Python虚拟环境来保持不同项目所需的软件包。

为了创建一个虚拟环境,我们首先安装virtualenv

在你的终端上运行以下命令。

pip install virtualenv
virtualenv env

让我们激活我们的虚拟环境。

  • Mac OS / Linux。
source env/bin/activate
  • Windows。
env\Scripts\activate

让我们继续设置我们的Django依赖性。

pip install django

一旦我们安装了Django,我们将分别创建我们的电子商务项目和应用程序。

django-admin startproject ecommerce
cd ecommerce
django-admin startapp products

现在,我们将进入我们的代码编辑器。在你的代码编辑器中打开项目,在你的项目settings.py文件中,通过注册你的应用程序。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products',
]

创建模型

下一步,我们将在products/models.py文件中创建我们的产品应用模型。

from django.db import models

# Create your models here.
class Category(models.Model):
    title = models.CharField(max_length=255)

    class Meta:
        verbose_name_plural = 'Categories'
    def __str__(self):
        return self.title

class Book(models.Model):
    title = models.CharField(max_length=150)
    author = models.CharField(max_length=100, default='John Doe')
    isbn = models.CharField(max_length=13)
    pages = models.IntegerField()
    price = models.IntegerField()
    quantity = models.IntegerField()
    description = models.TextField()
    status = models.BooleanField()
    date_created = models.DateField(auto_now_add=True)

    class Meta:
        ordering = ['-date_created']

    def __str__(self):
        return self.title

class Grocery(models.Model):
    product_tag = models.CharField(max_length=10)
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='grocery', on_delete=models.CASCADE)
    price = models.IntegerField()
    quantity = models.IntegerField()
    imageurl = models.URLField()
    status = models.BooleanField()
    date_created = models.DateField(auto_now_add=True)

    class Meta:
        ordering = ['-date_created']

    def __str__(self):
        return self.name

因此,让我们讨论一下我们在上面的代码中到底做了什么。

  • 我们创建了三个模型类,Category、BookGrocery。
  • 我们为模型类添加了字段。
  • 通过-date_created ,这些模型将根据它们的创建日期来排序。

下一步,让我们在我们的products/admin.py 文件中注册我们的模型。

from django.contrib import admin
from .models import Category, Book, Grocery

# Register your models here.

admin.site.register(Category)
admin.site.register(Book)
admin.site.register(Grocery)

让我们继续在我们的终端运行模型的迁移。通过运行迁移,这些模型被添加到我们的数据库中。

在你的终端运行以下命令。

python manage.py makemigrations
python manage.py migrate

一旦迁移完成,在你的终端中运行以下命令来启动应用程序。

python manage.py runserver

在你的终端中点击链接[http://127.0.0.1:8000/](http://127.0.0.1:8000/) 。如果应用程序显示在你的浏览器上,那么你就走上了正轨。

将GraphQL整合到我们的项目中

我们将把GraphQL整合到我们的Django项目中。首先,让我们安装一个名为Graphene-Django的软件包。

在你的终端上运行。

pip install graphene-django

下一步,将 graphene_djangoINSTALLED_APPS 在你的settings.py 文件中。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products',
    'graphene_django',
]

将GraphQL添加到URL中

在使用GraphQL时,客户端可以访问的唯一端点/API是**/graphql**。这是唯一的端点,客户可以通过它来请求和改变数据。因此,与REST相比,我们需要管理的端点较少。

要在我们的URL中添加一个GraphQL视图,在ecommerce/urls.py 文件中。

添加以下内容。

from django.contrib import admin
from django.urls import path
from graphene_django.views import GraphQLView
from products.schema import schema

urlpatterns = [
    path('admin/', admin.site.urls),
    path("graphql", GraphQLView.as_view(graphiql=True, schema=schema)),
]

该URL包含我们的端点,我们的GraphQL通信将在这里进行。我们导入了GraphQLView ,这是一个由graphene_django 提供的独特视图,当Graphql url被调用时,它将被执行。

然后,我们添加了一个名为graphql的URL。然后,我们设置 graphiql=True这将使我们能够使用graphiql。

创建一个模式

GraphQL是一种查询语言,有一个强大的类型系统,可以用来定义API的数据结构。GraphQL模式被用来表示这些信息。

模式是客户端和服务器之间的契约,描述了客户端如何获得对数据库的访问。

你需要添加一个模式、对象类型和一个接收GraphQL查询的视图函数,以便能够在你的Web应用程序中执行GraphQL查询。

让我们来定义我们的模式,在products/ 目录中,我们将创建一个名为schema.py的文件并添加以下内容。

import graphene
from graphene_django import DjangoObjectType
from .models import Category, Book, Grocery

class CategoryType(DjangoObjectType):
    class Meta: 
        model = Category
        fields = ('id','title')

  
class BookType(DjangoObjectType):
    class Meta: 
        model = Books
        fields = (
            'id',
            'title',
            'author',
            'isbn',
            'pages', 
            'price',
            'quantity', 
            'description',
            'imageurl',
            'status',
            'date_created',
        )  

class GroceryType(DjangoObjectType):
    class Meta:
        model = Grocery
        fields = (
            'product_tag',
            'name',
            'category',
            'price',
            'quantity',
            'imageurl',
            'status',
            'date_created',
        )

class Query(graphene.ObjectType):
    categories = graphene.List(CategoryType)
    books = graphene.List(BookType)
    groceries = graphene.List(GroceryType)

    def resolve_books(root, info, **kwargs):
        # Querying a list
        return Book.objects.all()

    def resolve_categories(root, info, **kwargs):
        # Querying a list
        return Category.objects.all()

    def resolve_groceries(root, info, **kwargs):
        # Querying a list
        return Grocery.objects.all()
schema = graphene.Schema(query=Query)

在上面的代码中。

  • 我们为我们的三个模型(Category, Book, and Grocery)创建了一个模式。
  • 我们还包括DjangoObjectType :它使用 GraphQL 来显示模型上的所有字段。
  • class Query继承自*'graphene.ObjectType'*,为我们的Graphql查询提供设置。
  • resolve_categories, books, groceries术语:用于打开类别、书籍、杂货查询集。这些方法接受两个参数(root和info)。
  • graphene.Schema检索:这个查询从我们的类型(数据库)中带来数据。

测试我们的GraphQL API

接下来,我们将测试我们的API,以确保它成功运行。要做到这一点,让我们简单地运行python manage.py runserver

让我们检查一下我们的URLhttp://120.0.0.1:8000/graphql

让我们尝试一些功能来查询我们数据库中的数据。我们将通过使用GraphQL预览来做到这一点,它是导航栏左上方的播放按钮。

{
  books{
      id
      title
      author
      isbn
      pages 
      price
      quantity
      description
      status
    }
}

我们的数据是空的,因为我们没有向数据库添加任何数据。我们不能忘记的一个重要步骤是创建一个管理用户。让我们通过在终端上运行以下几行代码来简要地做这件事。

python manage.py createsuperuser

添加用户名和密码。超级用户成功创建,现在你可以使用http://127.0.0.1:8000/admin/ ,在你的浏览器上运行管理网站。

你可以向任何一个模型中添加数据。

添加突变

在GraphQL中,突变是在添加、更新和删除数据时使用的。它执行的功能与REST API中的POST、DELETE和PUT方法类似。

在你的schema.py文件中添加以下几行代码。

class UpdateCategory(graphene.Mutation):
    class Arguments:
        # Mutation to update a category 
        title = graphene.String(required=True)
        id = graphene.ID()


    category = graphene.Field(CategoryType)

    @classmethod
    def mutate(cls, root, info, title, id):
        category = Category.objects.get(pk=id)
        category.title = title
        category.save()
        
        return UpdateCategory(category=category)

class CreateCategory(graphene.Mutation):
    class Arguments:
        # Mutation to create a category
        title = graphene.String(required=True)

    # Class attributes define the response of the mutation
    category = graphene.Field(CategoryType)

    @classmethod
    def mutate(cls, root, info, title):
        category = Category()
        category.title = title
        category.save()
        
        return CreateCategory(category=category)

class BookInput(graphene.InputObjectType):
    title = graphene.String()
    author = graphene.String()
    pages = graphene.Int()
    price = graphene.Int()
    quantity = graphene.Int()
    description = graphene.String()
    status = graphene.String()

class CreateBook(graphene.Mutation):
    class Arguments:
        input = BookInput(required=True)

    book = graphene.Field(BookType)
    
    @classmethod
    def mutate(cls, root, info, input):
        book = Book()
        book.title = input.title
        book.author = input.author
        book.pages = input.pages
        book.price = input.price
        book.quantity = input.quantity
        book.description = input.description
        book.status = input.status
        book.save()
        return CreateBook(book=book)

class UpdateBook(graphene.Mutation):
    class Arguments:
        input = BookInput(required=True)
        id = graphene.ID()

    book = graphene.Field(BookType)
    
    @classmethod
    def mutate(cls, root, info, input, id):
        book = Product.objects.get(pk=id)
        book.name = input.name
        book.description = input.description
        book.price = decimal.Decimal(input.price)
        book.quantity = input.quantity
        book.save()
        return UpdateBook(book=book)

class Mutation(graphene.ObjectType):
    update_category = UpdateCategory.Field()
    create_category = CreateCategory.Field()
    create_book = CreateBook.Field()
    update_book = UpdateBook.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)
  • 我们创建了类来添加和更新数据到我们的模型。
  • 'class argument'允许我们定义一个参数来保存数据到数据库。
  • 'class Mutation'定义了我们的突变,并发送参数,如更新和创建数据到模型中。
  • 最后,我们通过向模式构造器添加突变来更新我们的模式。

接下来,我们继续测试我们的突变和查询。让我们创建一个新的类别。

把下面的突变粘贴在左边,然后点击播放按钮。

mutation {
 create_category:createCategory(title :"Plastic") {
  category {
   id,
   title,
  }
 }
}
mutation {
  create_book: createBook(input: {title:"Imagine this",author: "Shola", pages: 12, price: 1200, quantity: 4, description:"a brief description", status: "True"}){
    book {
      id,
      title,
      author,
      pages,
      price,
      quantity,
      description,
      status
    }
  }
}

成功地添加到我们的数据库中!🎉

结语

使用Graphene-Django包,我们能够在本教程中把GraphQL纳入Django。

如果实施得当,Django中的GraphQL将产生一个极具可扩展性和通用性的应用程序。然而,我们并没有使用graphene包的所有功能。

本教程提供了一个关于GraphQL和Django如何整合的偷窥。GraphQL可以用来为你的Django应用程序添加各种额外的功能。

如果你正在开始使用GraphQL和Django,我希望这个教程能对你有所帮助!