Skip to content

🔷 Generate from GraphQL

Generate Pydantic models from GraphQL schema definitions.

🚀 Quick Start

datamodel-codegen \
    --input schema.graphql \
    --input-file-type graphql \
    --output-model-type pydantic_v2.BaseModel \
    --output model.py

Default output model

When --output-model-type is omitted, datamodel-code-generator generates Pydantic v2 BaseModel output (pydantic_v2.BaseModel). Pass --output-model-type explicitly when you want another model family.

📦 Installation

GraphQL support requires the graphql extra:

pip install 'datamodel-code-generator[graphql]'

📝 Simple Example

Let's consider a simple GraphQL schema (more details in GraphQL Schemas and Types).

schema.graphql

type Book {
  id: ID!
  title: String
  author: Author
}

type Author {
  id: ID!
  name: String
  books: [Book]
}

input BooksInput {
    ids: [ID!]!
}

input AuthorBooksInput {
    id: ID!
}

type Query {
  getBooks(input: BooksInput): [Book]
  getAuthorBooks(input: AuthorBooksInput): [Book]
}

✨ Generated model.py

# generated by datamodel-codegen:
#   filename:  schema.graphql
#   timestamp: 2023-11-20T17:04:42+00:00

from __future__ import annotations

from typing import TypeAlias

from pydantic import BaseModel, Field
from typing_extensions import Literal

# The `Boolean` scalar type represents `true` or `false`.
Boolean: TypeAlias = bool


# The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
ID: TypeAlias = str


# The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
String: TypeAlias = str


class Author(BaseModel):
    books: list[Book | None] | None = Field(default_factory=list)
    id: ID
    name: String | None = None
    typename__: Literal['Author'] | None = Field('Author', alias='__typename')


class Book(BaseModel):
    author: Author | None = None
    id: ID
    title: String | None = None
    typename__: Literal['Book'] | None = Field('Book', alias='__typename')


class AuthorBooksInput(BaseModel):
    id: ID
    typename__: Literal['AuthorBooksInput'] | None = Field(
        'AuthorBooksInput', alias='__typename'
    )


class BooksInput(BaseModel):
    ids: list[ID]
    typename__: Literal['BooksInput'] | None = Field(
        'BooksInput', alias='__typename'
    )


📤 Response Deserialization

For the following response of getAuthorBooks GraphQL query:

response.json

{
  "getAuthorBooks": [
    {
      "author": {
        "id": "51341cdscwef14r13",
        "name": "J. K. Rowling"
      },
      "id": "1321dfvrt211wdw",
      "title": "Harry Potter and the Prisoner of Azkaban"
    },
    {
      "author": {
        "id": "51341cdscwef14r13",
        "name": "J. K. Rowling"
      },
      "id": "dvsmu12e19xmqacqw9",
      "title": "Fantastic Beasts: The Crimes of Grindelwald"
    }
  ]
}

main.py

from model import Book

response = {...}

books = [
    Book.model_validate(book_raw) for book_raw in response["getAuthorBooks"]
]
print(books)
# [Book(author=Author(books=[], id='51341cdscwef14r13', name='J. K. Rowling', typename__='Author'), id='1321dfvrt211wdw', title='Harry Potter and the Prisoner of Azkaban', typename__='Book'), Book(author=Author(books=[], id='51341cdscwef14r13', name='J. K. Rowling', typename__='Author'), id='dvsmu12e19xmqacqw9', title='Fantastic Beasts: The Crimes of Grindelwald', typename__='Book')]


🎨 Custom Scalar Types

datamodel-codegen \
    --input schema.graphql \
    --input-file-type graphql \
    --output-model-type pydantic_v2.BaseModel \
    --extra-template-data data.json \
    --output model.py

schema.graphql

scalar Long

type A {
  id: ID!
  duration: Long!
}

data.json

{
  "Long": {
    "py_type": "int"
  }
}

✨ Generated model.py

# generated by datamodel-codegen:
#   filename:  custom-scalar-types.graphql
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Optional, TypeAlias

from pydantic import BaseModel, Field
from typing_extensions import Literal

# The `Boolean` scalar type represents `true` or `false`.
Boolean: TypeAlias = bool


# The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
ID: TypeAlias = str


Long: TypeAlias = int


# The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
String: TypeAlias = str


class A(BaseModel):
    duration: Long
    id: ID
    typename__: Optional[Literal['A']] = Field('A', alias='__typename')


🚫 Excluding __typename Field

When using generated models for GraphQL mutations, the __typename field may cause issues as GraphQL servers typically don't expect this field in input data.

Use the --graphql-no-typename option to exclude this field:

datamodel-codegen \
    --input schema.graphql \
    --input-file-type graphql \
    --output-model-type pydantic_v2.BaseModel \
    --graphql-no-typename \
    --output model.py

Before (default):

class Book(BaseModel):
    id: ID
    title: String | None = None
    typename__: Literal['Book'] | None = Field('Book', alias='__typename')

After (with --graphql-no-typename):

class Book(BaseModel):
    id: ID
    title: String | None = None

Union Type Discrimination

If your schema uses GraphQL union types and you rely on __typename for type discrimination during deserialization, excluding this field may break that functionality. Consider using this option only for input types or schemas without unions.

Supported GraphQL Features

Feature Generation behavior
Object and input object types Generated as model classes
Enums Generated as Python enum types
Scalars Built-in scalars map to Python aliases; custom scalars can be configured
Lists and non-null markers Converted into Python collection and optionality annotations
__typename Included by default and removable with --graphql-no-typename

Limitations

GraphQL input generates data models from schema definitions. It does not generate query builders, clients, resolvers, schema execution code, or runtime GraphQL validation.


📖 See Also