strawberry-graphql

Strawberry

Code-first Python GraphQL library using dataclasses and type hints

Details

Language / Topic
graphqlGraphQL
Category
framework

Rules

balanced
- Define types with `@strawberry.type` and `@strawberry.field` decorators — use Python dataclass-style field declarations with type hints for automatic schema generation.
- Use `@strawberry.input` for mutation input types and `strawberry.ID` for GraphQL ID scalars.
- Build the schema with `schema = strawberry.Schema(query=Query, mutation=Mutation)` — pass only the root types.
- Use `strawberry.UNSET` as the default for truly optional fields (distinct from `None`/null) to differentiate between "not provided" and "explicitly null".
- Prevent N+1 with `StrawberryDjangoOptimizer` (Django) or `DataLoader` (generic): batch related object lookups in a single DB query.
- Define types with `@strawberry.type` and field-level type hints — Strawberry generates the GraphQL schema automatically from Python types: `@strawberry.type\nclass User:\n id: strawberry.ID\n name: str\n email: str | None`.
- Use `@strawberry.field` for computed or resolver-backed fields: `@strawberry.field\nasync def posts(self, info: strawberry.types.Info) -> list[Post]: return await info.context.db.get_posts(user_id=self.id)`.
- Define mutation inputs with `@strawberry.input`: `@strawberry.input\nclass CreateUserInput:\n name: str\n email: str` and use them as typed mutation arguments.
- Use `strawberry.ID` for identifier fields — it serializes as a string in the GraphQL schema regardless of the underlying Python type.
- Use `strawberry.UNSET` as the default value for optional mutation fields to distinguish "field not provided" from `None` (explicit null).
- Return `strawberry.Private[str]` for fields computed internally but not exposed in the schema.
- Prevent N+1 with `DataLoader`: define a `load_fn` that batches IDs and register it in context — resolvers call `await info.context.loader.load(self.author_id)` instead of individual DB queries.