石墨烯 Pydantic 集成
项目描述
石墨烯-pydantic

安装
pip install "graphene-pydantic"
例子
这是一个简单的 Pydantic 模型:
import uuid
import pydantic
class PersonModel(pydantic.BaseModel):
id: uuid.UUID
first_name: str
last_name: str
要为其创建 GraphQL 模式,您只需编写以下代码:
import graphene
from graphene_pydantic import PydanticObjectType
class Person(PydanticObjectType):
class Meta:
model = PersonModel
# exclude specified fields
exclude_fields = ("id",)
class Query(graphene.ObjectType):
people = graphene.List(Person)
@staticmethod
def resolve_people(parent, info):
# fetch actual PersonModels here
return [PersonModel(id=uuid.uuid4(), first_name="Beth", last_name="Smith")]
schema = graphene.Schema(query=Query)
然后您可以简单地查询架构:
query = """
query {
people {
firstName,
lastName
}
}
"""
result = schema.execute(query)
print(result.data['people'][0])
输入对象类型
您还可以从 Pydantic 模型为突变和查询创建输入对象类型:
from graphene_pydantic import PydanticInputObjectType
class PersonInput(PydanticInputObjectType):
class Meta:
model = PersonModel
# exclude specified fields
exclude_fields = ("id",)
class CreatePerson(graphene.Mutation):
class Arguments:
person = PersonInput()
Output = Person
@staticmethod
def mutate(parent, info, person):
personModel = PersonModel(id=uuid.uuid4(), first_name=person.first_name, last_name=person.last_name)
# save PersonModel here
return person
class Mutation(graphene.ObjectType):
createPerson = CreatePerson.Field()
schema = graphene.Schema(mutation=Mutation)
然后使用输入执行:
mutation = '''
mutation {
createPerson(person: {
firstName: "Jerry",
lastName: "Smith"
}) {
firstName
}
}
'''
result = schema.execute(mutation)
print(result.data['createPerson']['firstName'])
自定义解析函数
由于PydanticObjectType继承自graphene.ObjectType您,因此可以添加自定义解析函数,如此处所述。例如:
class Person(PydanticObjectType):
class Meta:
model = PersonModel
# exclude specified fields
exclude_fields = ("id",)
full_name = graphene.String()
def resolve_full_name(self, info, **kwargs):
return self.first_name + ' ' + self.last_name
前向声明和循环引用
graphene_pydantic支持前向声明和循环引用,但您需要调用该resolve_placeholders()方法以确保在执行 GraphQL 查询之前完全更新类型。例如:
class NodeModel(BaseModel):
id: int
name: str
labels: 'LabelsModel'
class LabelsModel(BaseModel):
node: NodeModel
labels: typing.List[str]
class Node(PydanticObjectType):
class Meta:
model = NodeModel
class Labels(PydanticObjectType):
class Meta:
model = LabelsModel
Node.resolve_placeholders() # make the `labels` field work
Labels.resolve_placeholders() # make the `node` field work
完整示例
有关更多信息,请参阅示例目录。
执照
这个项目在Apache 许可下。
第三方代码
该项目依赖于第三方代码,该代码受第三方许可中规定的许可的约束。
贡献
注意事项
映射
请注意,即使 Pydantic 对包含映射的字段(例如字典)非常满意,因为GraphQL 的类型系统没有它们,这些字段不能导出到 Graphene 类型。例如,这将失败并出现错误Don't know how to handle mappings in Graphene:
import typing
from graphene_pydantic import PydanticObjectType
class Pet:
pass
class Person:
name: str
pets_by_name: typing.Dict[str, Pet]
class GraphQLPerson(PydanticObjectType):
class Meta:
model = Person
但是,请注意,如果您使用exclude_fields或only_fields排除这些值,则不会有问题:
class GraphQLPerson(PydanticObjectType):
class Meta:
model = Person
exclude_fields = ("pets_by_name",)
联合类型
使用 Unions 时有一些注意事项。让我们以以下 pydantic 模型作为本节的示例:
class EmployeeModel(pydantic.BaseModel):
name: str
class ManagerModel(EmployeeModel):
title: str
class DepartmentModel(pydantic.BaseModel):
employees: T.List[T.Union[ManagerModel, EmployeeModel]]
您必须is_type_of在石墨烯模型中实现类方法
要在石墨烯中获得ManagerModel并EmployeeModel成功解析,您需要is_type_of像这样实现:
class Employee(PydanticObjectType):
class Meta:
model = EmployeeModel
@classmethod
def is_type_of(cls, root, info):
return isinstance(root, (cls, EmployeeModel))
class Manager(PydanticObjectType):
class Meta:
model = ManagerModel
@classmethod
def is_type_of(cls, root, info):
return isinstance(root, (cls, ManagerModel))
class Department(PydanticObjectType):
class Meta:
model = DepartmentModel
否则 GraphQL 会抛出类似的错误"[GraphQLError('Abstract type UnionOfManagerModelEmployeeModel must resolve to an Object type at runtime for field Department.employees ..."
对于子类之间的联合,需要把子类放在类型注解的前面
看employees上面的字段,如果你先用Employee写类型注解
employees: T.List[T.Union[EmployeeModel, ManagerModel]],你将无法查询到经理相关的字段(在这种情况下title)。在包含这样一个价差的查询中:
...on Employee {
name
}
...on Manager {
name
title
}
...对象将始终解析为Employee. 如果将子类放在注释列表的首位,则可以避免这种情况:employees: T.List[T.Union[ManagerModel, EmployeeModel]].
子类之间的联合在 Python 3.6 中不起作用
如果模型上的字段是类和子类之间的联合(如我们的示例中所示),Python 3.6 的类型将不会保留联合并丢弃子类的注释。有关详细信息,请参阅此问题。目前的解决方案是使用 Python 3.7。
输入对象类型不支持联合作为字段
这是 GraphQL 的限制。有关支持输入联合的进展,请参阅此 RFC。如果您看到“{union-type} 可能仅包含对象类型”之类的错误,则您很可能遇到此限制。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。