{"id":13633923,"url":"https://github.com/graphql-python/graphene-pydantic","last_synced_at":"2025-05-15T04:07:57.515Z","repository":{"id":41895121,"uuid":"192823583","full_name":"graphql-python/graphene-pydantic","owner":"graphql-python","description":"Integrate GraphQL with your Pydantic models","archived":false,"fork":false,"pushed_at":"2025-01-14T01:38:27.000Z","size":347,"stargazers_count":241,"open_issues_count":17,"forks_count":44,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-15T00:22:47.201Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/graphql-python.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-20T00:49:40.000Z","updated_at":"2025-04-10T15:51:02.000Z","dependencies_parsed_at":"2025-01-17T16:06:15.593Z","dependency_job_id":"db30dc76-5110-446d-8853-a70599f71e02","html_url":"https://github.com/graphql-python/graphene-pydantic","commit_stats":{"total_commits":212,"total_committers":25,"mean_commits":8.48,"dds":0.6650943396226415,"last_synced_commit":"c1e47197fbacebe1fc586f2d33cde7fb70f0302a"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-python%2Fgraphene-pydantic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-python%2Fgraphene-pydantic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-python%2Fgraphene-pydantic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/graphql-python%2Fgraphene-pydantic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/graphql-python","download_url":"https://codeload.github.com/graphql-python/graphene-pydantic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270646,"owners_count":22042859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T23:00:53.742Z","updated_at":"2025-05-15T04:07:52.496Z","avatar_url":"https://github.com/graphql-python.png","language":"Python","readme":"# ![Graphene Logo](http://graphene-python.org/favicon.png) graphene-pydantic [![Build status](https://circleci.com/gh/upsidetravel/graphene-pydantic.svg?style=svg)](https://circleci.com/gh/upsidetravel/graphene-pydantic) [![PyPI version](https://badge.fury.io/py/graphene-pydantic.svg)](https://badge.fury.io/py/graphene-pydantic) [![Coverage Status](https://coveralls.io/repos/upsidetravel/graphene-pydantic/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/upsidetravel/graphene-pydantic?branch=master)\n\n\n\nA [Pydantic](https://pydantic-docs.helpmanual.io/) integration for [Graphene](http://graphene-python.org/).\n\n## Installation\n\n```bash\npip install \"graphene-pydantic\"\n```\n\n## Examples\n\nHere is a simple Pydantic model:\n\n```python\nimport uuid\nimport pydantic\n\nclass PersonModel(pydantic.BaseModel):\n    id: uuid.UUID\n    first_name: str\n    last_name: str\n```\n\nTo create a GraphQL schema for it you simply have to write the following:\n\n```python\nimport graphene\nfrom graphene_pydantic import PydanticObjectType\n\nclass Person(PydanticObjectType):\n    class Meta:\n        model = PersonModel\n        # exclude specified fields\n        exclude_fields = (\"id\",)\n\nclass Query(graphene.ObjectType):\n    people = graphene.List(Person)\n\n    @staticmethod\n    def resolve_people(parent, info):\n        # fetch actual PersonModels here\n        return [PersonModel(id=uuid.uuid4(), first_name=\"Beth\", last_name=\"Smith\")]\n\nschema = graphene.Schema(query=Query)\n```\n\nThen you can simply query the schema:\n\n```python\nquery = \"\"\"\n    query {\n      people {\n        firstName,\n        lastName\n      }\n    }\n\"\"\"\nresult = schema.execute(query)\nprint(result.data['people'][0])\n```\n\n### Input Object Types\n\nYou can also create input object types from Pydantic models for mutations and queries:\n\n```python\nfrom graphene_pydantic import PydanticInputObjectType\n\nclass PersonInput(PydanticInputObjectType):\n    class Meta:\n        model = PersonModel\n        # exclude specified fields\n        exclude_fields = (\"id\",)\n\nclass CreatePerson(graphene.Mutation):\n    class Arguments:\n        person = PersonInput()\n\n    Output = Person\n\n    @staticmethod\n    def mutate(parent, info, person):\n        personModel = PersonModel(id=uuid.uuid4(), first_name=person.first_name, last_name=person.last_name)\n        # save PersonModel here\n        return person\n\nclass Mutation(graphene.ObjectType):\n    createPerson = CreatePerson.Field()\n\nschema = graphene.Schema(mutation=Mutation)\n```\n\nThen execute with the input:\n\n```python\nmutation = '''\nmutation {\n    createPerson(person: {\n        firstName: \"Jerry\",\n        lastName: \"Smith\"\n    }) {\n        firstName\n    }\n}\n'''\nresult = schema.execute(mutation)\nprint(result.data['createPerson']['firstName'])\n```\n\n### Custom resolve functions\n\nSince `PydanticObjectType` inherits from `graphene.ObjectType` you can add custom resolve functions as explained [here](https://docs.graphene-python.org/en/stable/api/#object-types). For instance:\n\n```python\nclass Person(PydanticObjectType):\n    class Meta:\n        model = PersonModel\n        # exclude specified fields\n        exclude_fields = (\"id\",)\n\n    full_name = graphene.String()\n\n    def resolve_full_name(self, info, **kwargs):\n        return self.first_name + ' ' + self.last_name\n```\n\n\n### Forward declarations and circular references\n\n`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:\n\n``` python\nclass NodeModel(BaseModel):\n    id: int\n    name: str\n    labels: 'LabelsModel'\n\nclass LabelsModel(BaseModel):\n    node: NodeModel\n    labels: typing.List[str]\n\nclass Node(PydanticObjectType):\n    class Meta:\n        model = NodeModel\n\nclass Labels(PydanticObjectType):\n    class Meta:\n        model = LabelsModel\n\n\nNode.resolve_placeholders()  # make the `labels` field work\nLabels.resolve_placeholders()  # make the `node` field work\n```\n\n### Full Examples\n\nPlease see [the examples directory](./examples) for more.\n\n### License\n\nThis project is under the [Apache License](./LICENSE.md).\n\n### Third Party Code\n\nThis project depends on third-party code which is subject to the licenses set forth in [Third Party Licenses](./THIRD_PARTY_LICENSES.md).\n\n### Contributing\n\nPlease see the [Contributing Guide](./CONTRIBUTING.md).\n\n### Caveats\n\n#### Mappings\n\nNote that even though Pydantic is perfectly happy with fields that hold mappings (e.g. dictionaries), because [GraphQL's type system doesn't have them](https://graphql.org/learn/schema/) 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`:\n\n``` python\nimport typing\nfrom graphene_pydantic import PydanticObjectType\n\nclass Pet:\n    pass\n\nclass Person:\n    name: str\n    pets_by_name: typing.Dict[str, Pet]\n\nclass GraphQLPerson(PydanticObjectType):\n    class Meta:\n        model = Person\n```\n\nHowever, note that if you use `exclude_fields` or `only_fields` to exclude those values, there won't be a problem:\n\n``` python\nclass GraphQLPerson(PydanticObjectType):\n    class Meta:\n        model = Person\n        exclude_fields = (\"pets_by_name\",)\n```\n\n#### Union types\n\nThere are some caveats when using Unions. Let's take the following pydantic models as an example for this section:\n\n```python\nclass EmployeeModel(pydantic.BaseModel):\n    name: str\n\n\nclass ManagerModel(EmployeeModel):\n    title: str\n\n\nclass DepartmentModel(pydantic.BaseModel):\n    employees: T.List[T.Union[ManagerModel, EmployeeModel]]\n```\n\n##### You have to implement the class method `is_type_of` in the graphene models\n\nTo get the Union between `ManagerModel` and `EmployeeModel` to successfully resolve\nin graphene, you need to implement `is_type_of` like this:\n\n```python\nclass Employee(PydanticObjectType):\n    class Meta:\n        model = EmployeeModel\n\n    @classmethod\n    def is_type_of(cls, root, info):\n        return isinstance(root, (cls, EmployeeModel))\n\n\nclass Manager(PydanticObjectType):\n    class Meta:\n        model = ManagerModel\n\n    @classmethod\n    def is_type_of(cls, root, info):\n        return isinstance(root, (cls, ManagerModel))\n\n\nclass Department(PydanticObjectType):\n    class Meta:\n        model = DepartmentModel\n```\n\nOtherwise GraphQL will throw an error similar to `\"[GraphQLError('Abstract type\nUnionOfManagerModelEmployeeModel must resolve to an Object type at runtime for\nfield Department.employees ...\"`\n\n##### For unions between subclasses, you need to put the subclass first in the type annotation\n\nLooking at the `employees` field above, if you write the type annotation with Employee first,\n`employees: T.List[T.Union[EmployeeModel, ManagerModel]]`, you will not be able to query\nmanager-related fields (in this case `title`). In a query containing a spread like this:\n\n```\n...on Employee {\n  name\n}\n...on Manager {\n  name\n  title\n}\n```\n\n... the objects will always resolve to being an `Employee`. This can be avoided if you put\nthe subclass first in the list of annotations: `employees: T.List[T.Union[ManagerModel, EmployeeModel]]`.\n\n##### Unions between subclasses don't work in Python 3.6\n\nIf a field on a model is a Union between a class and a subclass (as in our example),\nPython 3.6's typing will not preserve the Union and throws away the annotation for the subclass.\nSee [this issue](https://github.com/upsidetravel/graphene-pydantic/issues/11) for more details.\nThe solution at present is to use Python 3.7.\n\n##### Input Object Types don't support unions as fields\n\nThis is a GraphQL limitation. See [this RFC](https://github.com/graphql/graphql-spec/blob/master/rfcs/InputUnion.md) for the progress on supporting input unions. If you see an error like '{union-type} may only contain Object types', you are most likely encountering this limitation.\n","funding_links":[],"categories":["Topics Index","GraphQL Utilities"],"sub_categories":["Commonly Useful Knowledge"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql-python%2Fgraphene-pydantic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraphql-python%2Fgraphene-pydantic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphql-python%2Fgraphene-pydantic/lists"}