器→工具, 开源项目

API 的查询语言GraphQL与Graphene

钱魏Way · · 39 次浏览

GraphQL简介

GraphQL 是由 Facebook 开发的一种用于构建 API 的查询语言和运行时环境。与传统的 REST API 不同,GraphQL 允许客户端灵活地指定所需的数据结构,从而实现更高效的客户端-服务器交互。

GraphQL 的核心概念

  • 查询语言:客户端通过 GraphQL 查询语言指定所需的数据结构,服务器只返回这些数据。例如,一次请求可以获取多个相关数据对象,而无需发送多个请求。
  • 运行时环境:GraphQL 的运行时基于类型系统,将查询映射到服务器上的数据和代码。
  • 声明式数据获取:客户端声明“需要什么数据”,服务器返回精确匹配的结果,无多余数据或字段。

GraphQL 的主要特点

  • 单一端点:REST API 通常为不同资源定义多个端点,GraphQL 则通过一个端点处理所有查询请求。示例:
    • REST: /users, /users/:id/posts
    • GraphQL: /graphql(单一端点)
  • 灵活性:客户端指定所需的数据,不多不少。
    • REST 中:
      • /users 返回所有用户,可能包含不需要的字段。
      • /users/123/posts 返回与用户相关的所有帖子,可能需要多个请求。
    • GraphQL 中:单次请求即可获取精确的用户和其相关帖子信息。
  • 类型系统
    • GraphQL 使用 schema(模式)定义 API 数据的结构,包括数据类型、字段、关联关系等。
    • 强类型系统保证查询的正确性,非法查询在执行前就会报错。
  • 实时功能:GraphQL 支持实时更新数据,通过 Subscriptions(订阅)机制监听服务端的变化。
  • 解决过度获取和不足获取的问题
    • 过度获取(Overfetching):API 返回了客户端未使用的数据。
    • 不足获取(Underfetching):需要发送多个请求才能获取完整数据。
    • GraphQL 允许客户端请求精确的数据,避免上述问题。

GraphQL 与 REST API 的对比

特性 REST API GraphQL
端点数量 多个端点(/users, /posts) 单一端点(/graphql)
数据获取 可能过度或不足 精确匹配客户端请求数据
实时更新 需要额外实现机制 内置 Subscription
灵活性 固定数据结构 客户端灵活指定所需字段
强类型支持 通常依赖约定 内置类型系统
网络请求数量 多次请求 一次请求

GraphQL的优缺点

GraphQL 的主要优点

  • 高效数据获取:减少请求次数,避免过度或不足获取。
  • 灵活性:客户端可以完全控制返回的数据结构。
  • 强类型系统:开发中提供明确的 API 文档,减少错误。
  • 实时能力:内置 Subscription 支持实时数据更新。
  • 简化 API 版本管理:不需要引入新的版本(如 /v1、/v2),通过添加新字段实现非破坏性更新。

GraphQL 的主要缺点

  • 复杂性增加:服务端实现和部署复杂,需要额外开发解析器和模式。
  • 缓存困难:与 REST API 的 URL 缓存机制不同,GraphQL 的查询缓存需要更复杂的策略(如 Apollo Cache)。
  • 性能问题:如果查询过于复杂,可能导致服务端性能下降。
  • 学习成本:对开发者和运维团队来说,需要额外学习 GraphQL 和相关工具。
  • 权限控制复杂:精细化的查询可能导致复杂的权限管理。

典型使用场景

  • 复杂前端应用:需要整合多个数据源,或需要频繁修改 API 的前端应用(如 React/Vue 项目)。
  • 移动端应用:在带宽受限的情况下,高效获取所需数据。
  • 微服务架构:在服务端聚合多个微服务的数据,统一暴露给客户端。
  • 实时更新需求:比如聊天系统、股票交易系统等需要动态数据更新的场景。

GraphQL的使用

GraphQL 的工具与生态

  • 客户端工具
    • Apollo Client(最常用的 GraphQL 客户端)。
    • Relay(由 Facebook 开发,适合大型项目)。
  • 服务端框架
    • Apollo Server(js)。
    • Graphene(Python)。
    • GraphQL-Java(Java)。
    • Sangria(Scala)。
  • 调试工具
    • GraphiQL:基于浏览器的交互式 IDE。
    • Playground:GraphQL 查询调试工具。

GraphQL 的工作流程

  • 定义 Schema
    • 服务端使用 schema 描述数据类型及其关系。
    • GraphQL 提供了强类型语言,用来验证客户端的查询是否合法。
  • 客户端发送查询:客户端根据需要构建查询,指定需要的字段。
  • 服务端解析查询:服务端使用解析器(Resolver)执行查询,解析器从数据库或其他数据源获取所需数据。
  • 返回响应:服务端根据客户端的查询结构,返回精确匹配的数据。

GraphQL 的基本术语

Schema(模式)

定义了数据类型、查询方法以及对象之间的关系。

示例:

type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String
}

Query(查询)

用于获取数据的请求。

示例:

query {
  user(id: "123") {
    id
    name
    posts {
      title
      content
    }
  }
}

Mutation(变更)

用于修改数据,例如创建、更新、删除操作。

示例:

mutation {
  createPost(input: { title: "New Post", content: "GraphQL is awesome!" }) {
    id
    title
  }
}

Subscription(订阅)

用于监听服务端数据的实时更新。

示例:

subscription {
  postAdded {
    id
    title
    content
  }
}

Python工具Graphene

Graphene 是一个基于 Python 的开源框架,用于构建 GraphQL API。它简化了在 Python 环境中实现 GraphQL 的过程,是开发者在 Django、Flask 或独立服务中使用 GraphQL 的主要工具之一。

Graphene 的核心概念

  • 基于 Python 对象的实现
    • 使用 Python 的类和对象定义 GraphQL Schema 和解析器(Resolver)。
    • Schema 和 Query 通过面向对象的方式组织,开发者可以直观地管理数据结构。
  • 支持多种后端框架:Graphene 可以无缝集成到 Django、Flask 等框架中,也支持独立运行。
  • 兼容性:完全兼容 GraphQL 规范,支持所有的 查询变更(Mutations)订阅(Subscriptions)
  • 内置工具:提供开发和调试工具,如自动生成的 GraphQL 文档和交互式 IDE(如 GraphiQL)。

Graphene 的特点

声明式 Schema 定义

使用类定义 Schema 和字段,通过代码清晰地描述数据结构和类型关系。示例:

import graphene

class User(graphene.ObjectType):
    id = graphene.ID()
    name = graphene.String()

内置 GraphQL 类型

提供所有 GraphQL 规范中的基本类型,如 String、Int、Boolean、ID 等。

强类型系统

Graphene 强制类型检查,确保在开发和运行时避免无效查询。

易于扩展

可以结合 Django ORM 或 SQLAlchemy 等数据库工具快速生成复杂的数据模型。

高效开发

与 Python 的语法风格一致,易于 Python 开发者快速上手。

Graphene 的优缺点

优点

  • Pythonic:与 Python 语言风格一致,降低了学习成本。
  • 高效集成:支持 Django、Flask 等常见框架,结合 ORM 简化数据处理。
  • 强类型支持:内置类型系统可在开发阶段发现问题,提升可靠性。
  • 社区活跃:丰富的文档和社区资源,支持多种扩展。

缺点

  • 性能开销:对于复杂查询,解析器可能导致性能瓶颈。建议结合缓存机制优化性能。
  • 学习成本:需要学习 GraphQL 和 Graphene 的开发方式,对于新手有一定挑战。
  • 工具支持有限:与更成熟的框架(如 Apollo)相比,Graphene 的生态工具较少。

使用场景

  • 与 Django 深度集成:将现有的 Django 项目改造成 GraphQL API。
  • 独立 GraphQL 服务:构建纯 Python 的 GraphQL API 服务,适合快速开发小型项目。
  • 复杂数据模型:当应用中存在复杂的数据关联或自定义字段时,Graphene 提供了灵活的定义方式。
  • 移动端应用:为移动端提供高效的数据接口,减少多次网络请求。

Graphene 的主要组件

ObjectType

Graphene 的核心组件,用于定义 GraphQL 中的对象类型。

示例:

import graphene

class User(graphene.ObjectType):
    id = graphene.ID()
    name = graphene.String()

Query

定义查询(Query)操作,用于获取数据。

示例:

class Query(graphene.ObjectType):
    hello = graphene.String()

    def resolve_hello(root, info):
        return "Hello, Graphene!"

Mutations

定义数据的变更操作(新增、更新、删除)。

示例:

class CreateUser(graphene.Mutation):
    class Arguments:
        name = graphene.String()

    ok = graphene.Boolean()
    user = graphene.Field(lambda: User)

    def mutate(root, info, name):
        user = User(name=name)
        return CreateUser(user=user, ok=True)

Schema

Schema 是 Graphene 的入口点,用于注册查询和变更。

示例:

schema = graphene.Schema(query=Query, mutation=CreateUser)

Graphene 的使用流程

以下是一个简单的 Graphene 应用程序的开发流程:

安装 Graphene

pip install graphene

定义 Schema

定义数据结构、查询和变更。

import graphene

# 定义数据类型
class User(graphene.ObjectType):
    id = graphene.ID()
    name = graphene.String()

# 定义查询操作
class Query(graphene.ObjectType):
    hello = graphene.String()

    def resolve_hello(root, info):
        return "Hello, GraphQL!"

# 定义变更操作
class CreateUser(graphene.Mutation):
    class Arguments:
        name = graphene.String()

    ok = graphene.Boolean()
    user = graphene.Field(lambda: User)

    def mutate(root, info, name):
        user = User(name=name)
        return CreateUser(user=user, ok=True)

# 注册 Schema
class Mutation(graphene.ObjectType):
    create_user = CreateUser.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

运行查询

使用 execute 方法执行查询或变更。

query = '''
    query {
        hello
    }
'''

result = schema.execute(query)
print(result.data['hello'])  # 输出:Hello, GraphQL!

Graphene 与 Django 的集成

Graphene 提供了对 Django 的内置支持(通过 graphene-django 包),可以与 Django ORM 数据模型无缝对接。

安装 Graphene-Django

pip install graphene-django

配置 Django 项目

在 settings.py 中添加配置:

INSTALLED_APPS = [
    ...
    "graphene_django",
]

GRAPHENE = {
    "SCHEMA": "myproject.schema.schema",  # 指定 Schema 路径
}

定义 GraphQL API

以下是一个基于 Django 模型的 GraphQL API 示例:

# models.py
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)

# schema.py
import graphene
from graphene_django.types import DjangoObjectType
from .models import User

# 定义 Django 对象类型
class UserType(DjangoObjectType):
    class Meta:
        model = User

# 定义查询
class Query(graphene.ObjectType):
    users = graphene.List(UserType)

    def resolve_users(root, info):
        return User.objects.all()

schema = graphene.Schema(query=Query)

配置 URL 路由

在 urls.py 中添加 GraphQL 端点:

from graphene_django.views import GraphQLView

urlpatterns = [
    path("graphql/", GraphQLView.as_view(graphiql=True)),
]

访问 /graphql/,可以通过 GraphiQL 交互式工具测试查询。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注