一文读懂Graphene的Schema与Scalar

GraphQL是一种用于API的查询语言。

它提供了一种标准的方法:

描述服务器在静态类型架构中提供的数据

在查询中请求数据,该查询准确地描述了数据需求和在只包含请求的数据的响应中接收数据。

Graphene是一个库,在Python中实现GraphQLAPI的工具。

Graphene与最流行的web框架和ORM集成在一起,功能齐全。Graphene生成完全符合GraphQL规范的模式,并提供用于构建中继兼容API的工具和模式

安装Graphene:

pip3 install graphene

先来一个简单的例子

from graphene import ObjectType, String, Schema

class Query(ObjectType):
    # 定义了一个字段“hello”,其中只有一个参数“first_name”
    # 默认情况下,参数名称将自动以驼峰形式转换架构中的first_name为firstName
    hello = String(first_name=String(default_value="stranger"))
    goodbye = String()

    # resolver方法获取字段的GraphQL上下文(root,info)和 argument(first_name),并返回查询response的数据
    def resolve_hello(root, info, first_name):
        return f'Hello {first_name}!'

    def resolve_goodbye(root, info):
        return 'See you'

schema = Schema(query=Query)

Schema Definition Language (SDL)为:

GraphQL模式定义语言中,可以描述示例代码定义的字段

type Query {
  hello(firstName: String = "stranger"): String
  goodbye: String
}

查询

然后,可以通过传递GraphQL查询字符串来执行,从而开始查询Schema:

# 查询字段(使用默认参数)
query_string = '{ hello }'
result = schema.execute(query_string)
print(result.data['hello'])
# "Hello stranger!"

# 或在查询中传递参数
query_with_argument = '{ hello(firstName: "luwei") }'
result = schema.execute(query_with_argument)
print(result.data['hello'])
# "Hello luwei!"

Schema

GraphQL模式定义了API中字段之间的类型和关系。

Schema是通过提供每个操作、query(强制)、mutation和subscription的根ObjectType来创建的

Schema将收集与root操作相关的所有类型定义,然后将它们提供给validator和executor

my_schema = Schema(
    query=RootQuery,
    mutation=RootMutation,
    subscription=RootSubscription
)

RootQuery只是一种特殊的ObjectType,它定义了作为API入口点的字段。RootMutation和RootSubscription类似于RootQuery,但用于不同的操作类型:

query:查询获取数据

mutation:更改数据并检索更改

subscription:将更改实时发送到客户端

Querying

若要查询架构,请对其调用execute方法

query_string = 'query whoIsMyFriend { myBestFriend { lastName } }'   # whoIsMyBestFriend 可以不填
my_schema.execute(query_string)

Types

在某些情况下,Schema无法访问计划拥有的所有类型。例如,当一个字段返回一个Interface时,Schema不知道如何实现

在这种情况下,我们需要在创建Schema时使用types参数:

my_schema = Schema(
    query=RootQuery,
    types=[SomeExtraObjectType, ]
)

Auto camelCase field names

默认情况下,所有字段和参数名称都将从snake_case转换为camelCase(因为API通常由js/mobile客户端使用)

例如,对于ObjectType,last_name字段名将转换为lastName:

class Person(graphene.ObjectType):
    last_name = graphene.String()
    first_name = graphene.String(name='_first_Name')

如果不想转换,可以为字段构造函数提供一个名称参数。first_name转换为_first_Name(无需进一步转换)

查询应该如下:

{
    lastName
    _first_Name
}

要禁用转换,在Schema实例化时将auto_camelcase设置为False:

my_schema = Schema(
    query=RootQuery,
    auto_camelcase=False,
)

Scalars

Scalar类型表示查询叶子处的具体值。Graphene提供了几种开箱即用的内置类型,它们表示Python中的常见值。也可以创建自己的Scalar类型,以更好地表达数据模型中可能存在的值。

所有Scalar类型都接受以下参数。所有选项都是可选的 (除了以下这几个,传递的都为值参数):

name: string:覆盖字段的名称

description: string:显示的类型的描述

required: boolean: 如果为True,则将强制执行此字段的值,默认值为False

deprecation_reason: string: 描述字段的弃用理由

default_value: any: 为字段提供的默认值

内置的scalars

graphene.String : 表示文本数据,表示为UTF-8字符序列

graphene.Int: 整型

graphene.Float: 浮点型

graphene.Boolean:Bool型

graphene.ID:表示一个唯一的标识符,通常用于重写对象或作为缓存的键

graphene.Date: 日期值 例子如下:

import datetime
from graphene import Schema, ObjectType, Date

class Query(ObjectType):
    one_week_from = Date(required=True, date_input=Date(required=True)) # date_input为查询输入的参数

    def resolve_one_week_from(root, info, date_input):
        assert date_input == datetime.date(2023, 4, 3)
        return date_input + datetime.timedelta(weeks=1)

schema = Schema(query=Query)

results = schema.execute("""
    query {
        oneWeekFrom(dateInput: "2023-04-03")
    }
""")

assert results.data == {"oneWeekFrom": "2023-04-03"}

graphene.DateTime:DateTime值 例子如下:

import datetime
from graphene import Schema, ObjectType, DateTime

class Query(ObjectType):
    one_hour_from = DateTime(required=True, datetime_input=DateTime(required=True))

    def resolve_one_hour_from(root, info, datetime_input):
        assert datetime_input == datetime.datetime(2023, 4, 3, 15, 15, 5)
        return datetime_input + datetime.timedelta(hours=1)

schema = Schema(query=Query)

results = schema.execute("""
    query {
        oneHourFrom(datetimeInput: "2023-04-03T15:15:05")
    }
""")

assert results.data == {"oneHourFrom": "2023-04-03T15:15:05"}

graphene.Time: Time 值 例子如下:

import datetime
from graphene import Schema, ObjectType, Time

class Query(ObjectType):
    one_hour_from = Time(required=True, time_input=Time(required=True))

    def resolve_one_hour_from(root, info, time_input):
        assert time_input == datetime.time(15, 4, 5)
        tmp_time_input = datetime.datetime.combine(datetime.date(1, 1, 1), time_input)
        return (tmp_time_input + datetime.timedelta(hours=1)).time()

schema = Schema(query=Query)

results = schema.execute("""
    query {
        oneHourFrom(timeInput: "15:15:05")
    }
""")

assert results.data == {"oneHourFrom": "16:15:05"}

graphene.Decimal:Decimal值 例子如下:

import decimal
from graphene import Schema, ObjectType, Decimal

class Query(ObjectType):
    add_one_to = Decimal(required=True, decimal_input=Decimal(required=True))

    def resolve_add_one_to(root, info, decimal_input):
        assert decimal_input == decimal.Decimal("10.50")
        return decimal_input + decimal.Decimal("1")

schema = Schema(query=Query)

results = schema.execute("""
    query {
        addOneTo(decimalInput: "15.50")
    }
""")

assert results.data == {"addOneTo": "16.50"}

graphene.JSONString:JSON 类型 例子如下:

from graphene import Schema, ObjectType, JSONString, String

class Query(ObjectType):
    update_json_key = JSONString(
        required=True,
        json_input=JSONString(required=True),
        key=String(required=True),
        value=String(required=True)
    )

    def resolve_update_json_key(root, info, json_input, key, value):
        assert json_input == {"name": "lu wei"}
        json_input[key] = value
        return json_input

schema = Schema(query=Query)

results = schema.execute("""
    query {
        updateJsonKey(jsonInput: "{\\"name\\": \\"luwei\\"}", key: "height", value: "180")
    }
""")

assert results.data == {'updateJsonKey': '{"name": "lu wei", "height": "180"}'}

graphene.Base64: Base64 类型 例子如下:

from graphene import Schema, ObjectType, Base64

class Query(ObjectType):
    increment_encoded_id = Base64(
        required=True,
        base64_input=Base64(required=True),
    )

    def resolve_increment_encoded_id(root, info, base64_input):
        assert base64_input == "4"
        return int(base64_input) + 1

schema = Schema(query=Query)

results = schema.execute("""
    query {
        incrementEncodedId(base64Input: "NA==")
    }
""")

assert results.data == {"incrementEncodedId": "NQ=="}

自定义scalars

也可以为Schema创建自定义scalars。以下是创建DateTime scalars的示例:

import datetime
from graphene.types import Scalar
from graphql.language import ast

class DateTime(Scalar):
    '''自定义DateTime Scalar'''

    @staticmethod
    def serialize(dt):
        return dt.isoformat()

    @staticmethod
    def parse_instance(node, _variables=None):
      '''判断类型是否相等 并解析值'''
        if isinstance(node, ast.StringValueNode):
            return datetime.datetime.strptime(
                node.value, "%Y-%m-%dT%H:%M:%S.%f")

    @staticmethod
    def parse_value(value):
      '''解析值'''
        return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")

安装 Scalars

安装scalars在ObjectType、Interface或Mutation中充当字段

class Person(graphene.ObjectType):
    name = graphene.String()
# 等价与:
class Person(graphene.ObjectType):
    name = graphene.Field(graphene.String)

注意:当直接使用Field构造函数时,传递类型而不是实例

将scalars当作Field中的参数类型

graphene.Field(graphene.String, my_name=graphene.String())  # my_name 为值参数
# 等价于
graphene.Field(graphene.String, my_name=graphene.Argument(graphene.String))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芦苇浮绿水

觉得还不错请博主喝杯饮料

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值