Skip to main content

Graphene Pydantic integration

Project description

Graphene Logo graphene-pydantic Build status PyPI version Coverage Status

A Pydantic integration for Graphene.

Installation

pip install "graphene-pydantic"

Examples

Here is a simple Pydantic model:

import pydantic

class PersonModel(pydantic.BaseModel):
    id: uuid.UUID
    first_name: str
    last_name: str

To create a GraphQL schema for it you simply have to write the following:

import graphene
from graphene_pydantic import PydanticObjectType

class Person(PydanticObjectType):
    class Meta:
        model = PersonModel
        # only return specified fields
        only_fields = ("name",)
        # exclude specified fields
        exclude_fields = ("id",)

class Query(graphene.ObjectType):
    people = graphene.List(Person)

    def resolve_people(self, info):
        return get_people()  # function returning `PersonModel`s

schema = graphene.Schema(query=Query)

Then you can simply query the schema:

query = '''
    query {
      people {
        firstName,
        lastName
      }
    }
'''
result = schema.execute(query)

Forward declarations and circular references

graphene_pydantic supports forward declarations and circular references, but you will need to call the resolve_placeholders() method to ensure the types are fully updated before you execute a GraphQL query. For instance:

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

Full Examples

Please see the examples directory for more.

License

This project is under the Apache License.

Third Party Code

This project depends on third-party code which is subject to the licenses set forth in Third Party Licenses.

Contributing

Please see the Contributing Guide. Note that you must sign the CLA.

Caveats

Mappings

Note that even though Pydantic is perfectly happy with fields that hold mappings (e.g. dictionaries), because GraphQL's type system doesn't have them those fields can't be exported to Graphene types. For instance, this will fail with an error 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

However, note that if you use exclude_fields or only_fields to exclude those values, there won't be a problem:

class GraphQLPerson(PydanticObjectType):
  class Meta:
    model = Person
    exclude_fields = ("pets_by_name",)

Union types

There are some caveats when using Unions. Let's take the following pydantic models as an example for this section:

class EmployeeModel(pydantic.BaseModel):
    name: str


class ManagerModel(EmployeeModel):
    title: str


class DepartmentModel(pydantic.BaseModel):
    employees: T.List[T.Union[ManagerModel, EmployeeModel]]
You have to implement the class method is_type_of in the graphene models

To get the Union between ManagerModel and EmployeeModel to successfully resolve in graphene, you need to implement is_type_of like this:

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

Otherwise GraphQL will throw an error similar to "[GraphQLError('Abstract type UnionOfManagerModelEmployeeModel must resolve to an Object type at runtime for field Department.employees ..."

For unions between subclasses, you need to put the subclass first in the type annotation

Looking at the employees field above, if you write the type annotation with Employee first, employees: T.List[T.Union[EmployeeModel, ManagerModel]], you will not be able to query manager-related fields (in this case title). In a query containing a spread like this:

...on Employee {
  name
}
...on Manager {
  name
  title
}

... the objects will always resolve to being an Employee. This can be avoided if you put the subclass first in the list of annotations: employees: T.List[T.Union[ManagerModel, EmployeeModel]].

Unions between subclasses don't work in Python 3.6

If a field on a model is a Union between a class and a subclass (as in our example), Python 3.6's typing will not preserve the Union and throws away the annotation for the subclass. See this issue for more details. The solution at present is to use Python 3.7.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphene_pydantic-0.0.5.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

graphene_pydantic-0.0.5-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file graphene_pydantic-0.0.5.tar.gz.

File metadata

  • Download URL: graphene_pydantic-0.0.5.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/0.12.17 CPython/3.7.3 Linux/4.15.0-1043-aws

File hashes

Hashes for graphene_pydantic-0.0.5.tar.gz
Algorithm Hash digest
SHA256 3e2150dbdd82eba62733774bff8b6e14a97c390dd22696ebd98bf0db99936f4c
MD5 64697d7cb6af10e0a612f6ceb23c4b58
BLAKE2b-256 3674652b66f6d51ee3775530f46558d248dce7aa8a569697862df79166498199

See more details on using hashes here.

File details

Details for the file graphene_pydantic-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: graphene_pydantic-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/0.12.17 CPython/3.7.3 Linux/4.15.0-1043-aws

File hashes

Hashes for graphene_pydantic-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 801dc1b158dacf4f2fdba73ee38077de5e70cd642f5d8a59560bab0839d2bfd6
MD5 9e72807c03175e80bfbb5f5d614a0e2c
BLAKE2b-256 b4549ce5a6a274a88593ada95e0d1a178530f04a555eab29a5029f109aa24865

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page