# 🔷 Generate from GraphQL

Generate Pydantic models from GraphQL schema definitions.

## 🚀 Quick Start

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

!!! tip "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.

!!! note "📦 Installation"
    GraphQL support requires the `graphql` extra:
    ```bash
    pip install 'datamodel-code-generator[graphql]'
    ```

## 📝 Simple Example

Let's consider a simple GraphQL schema (more details in [GraphQL Schemas and Types](https://graphql.org/learn/schema/)).

**schema.graphql**
```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**
```python
# 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**
```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**
```python
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

```bash
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**
```graphql
scalar Long

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

**data.json**
```json
{
  "Long": {
    "py_type": "int"
  }
}
```

**✨ Generated model.py**
```python
# 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:

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

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

**After (with --graphql-no-typename):**
```python
class Book(BaseModel):
    id: ID
    title: String | None = None
```

!!! warning "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

- 🚀 [Getting Started](getting-started.md) - Installation and first model
- 🖥️ [CLI Reference](cli-reference/index.md) - Complete CLI options reference
- 🔧 [CLI Reference: Typing Customization](cli-reference/typing-customization.md) - Type annotation options
- 🎨 [CLI Reference: `--extra-template-data`](cli-reference/template-customization.md#extra-template-data) - Custom scalar type mappings
