| title | Queries |
|---|
Queries are the primary way to fetch data from your GraphQL API. Strawberry Django provides powerful tools to define queries that automatically map to Django models and querysets.
Queries can be written using strawberry_django.field() to load the fields defined in your types.
import strawberry
import strawberry_django
from .types import Fruit
@strawberry.type
class Query:
fruit: Fruit = strawberry_django.field()
fruits: list[Fruit] = strawberry_django.field()
schema = strawberry.Schema(query=Query)Tip
You must name your query class "Query" or decorate it with @strawberry.type(name="Query") for the single query default primary filter to work
For single queries (like fruit above), Strawberry Django automatically provides a primary key filter. The fruits query returns all objects by default.
query {
# Single object by primary key
fruit(pk: "1") {
id
name
}
# All objects
fruits {
id
name
}
}Add filters to your queries to enable flexible data filtering. Filters are defined in your types and automatically applied to queries.
import strawberry_django
from strawberry import auto
@strawberry_django.filter_type(models.Fruit, lookups=True)
class FruitFilter:
id: auto
name: auto
color: auto
@strawberry_django.type(models.Fruit, filters=FruitFilter)
class Fruit:
id: auto
name: auto
color: auto@strawberry.type
class Query:
fruits: list[Fruit] = strawberry_django.field()This enables powerful filtering in your GraphQL queries:
query {
# Exact match
fruits(filters: { name: "apple" }) {
id
name
}
# With lookups
fruits(filters: { name: { iContains: "berry" } }) {
id
name
}
# Complex filters with AND/OR
fruits(
filters: {
OR: [{ name: { startsWith: "straw" } }, { color: { exact: "red" } }]
}
) {
id
name
}
}See the Filtering Guide for comprehensive filter documentation.
Add ordering to control the sort order of your results.
import strawberry_django
from strawberry import auto
@strawberry_django.order_type(models.Fruit)
class FruitOrder:
name: auto
price: auto
@strawberry_django.type(models.Fruit, order=FruitOrder)
class Fruit:
id: auto
name: auto
price: autoquery {
# Order by name ascending
fruits(order: { name: ASC }) {
name
price
}
# Order by multiple fields
fruits(order: { price: DESC, name: ASC }) {
name
price
}
}See the Ordering Guide for detailed ordering documentation.
Always paginate large result sets to prevent performance issues.
from strawberry_django.pagination import OffsetPaginationInput
@strawberry.type
class Query:
@strawberry_django.field
def fruits(
self,
pagination: OffsetPaginationInput | None = None,
) -> list[Fruit]:
qs = models.Fruit.objects.all()
if pagination:
return qs[pagination.offset : pagination.offset + pagination.limit]
return qs[:100] # Default limitNote
Returning list[Fruit] means the queryset is evaluated immediately. For paginated queries with metadata (total count, page info), use OffsetPaginated[Fruit] with pagination=True instead. See the Pagination guide for details.
query {
fruits(pagination: { offset: 0, limit: 10 }) {
id
name
}
}from strawberry_django.relay import DjangoListConnection
import strawberry_django
@strawberry.type
class Query:
fruits: DjangoListConnection[Fruit] = strawberry_django.connection()query {
fruits(first: 10, after: "cursor") {
edges {
node {
id
name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}See the Pagination Guide for more pagination strategies.
Override default resolvers for custom query logic.
from strawberry.types import Info
@strawberry.type
class Query:
@strawberry_django.field
def fruits(
self,
info: Info,
available_only: bool = True,
) -> list[Fruit]:
qs = models.Fruit.objects.all()
if available_only:
qs = qs.filter(available=True)
# Apply filters from info context
return qs
@strawberry_django.field
def featured_fruits(self, info: Info) -> list[Fruit]:
"""Return only featured fruits"""
return models.Fruit.objects.filter(is_featured=True, available=True).order_by(
"-created_at"
)[:5]query {
# All available fruits
fruits(availableOnly: true) {
name
}
# Featured fruits only
featuredFruits {
name
}
}See the Custom Resolvers Guide for advanced resolver patterns.
For ASGI applications, you can define async queries for improved concurrency.
from asgiref.sync import sync_to_async
@strawberry.type
class Query:
@strawberry_django.field
async def fruits(self) -> list[Fruit]:
# Django ORM calls must be wrapped in sync_to_async
return await sync_to_async(list)(models.Fruit.objects.all())
@strawberry_django.field
async def fruit(self, pk: int) -> Fruit | None:
try:
return await sync_to_async(models.Fruit.objects.get)(pk=pk)
except models.Fruit.DoesNotExist:
return NoneWarning
Always wrap Django ORM operations in sync_to_async when using async resolvers. The ORM is not async-native.
Strawberry Django automatically handles related objects with optimal queries using the Query Optimizer.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)@strawberry_django.type(models.Author)
class Author:
id: auto
name: auto
books: list["Book"]
@strawberry_django.type(models.Book)
class Book:
id: auto
title: auto
author: Authorquery {
books {
title
author {
name
books {
title
}
}
}
}The Query Optimizer automatically adds select_related() and prefetch_related() to prevent N+1 queries.
See the Query Optimizer Guide for optimization details.
Add custom arguments to your queries for flexibility.
from datetime import date
@strawberry.type
class Query:
@strawberry_django.field
def books(
self,
author_id: int | None = None,
published_after: date | None = None,
min_rating: float | None = None,
) -> list[Book]:
qs = models.Book.objects.all()
if author_id:
qs = qs.filter(author_id=author_id)
if published_after:
qs = qs.filter(publication_date__gte=published_after)
if min_rating:
qs = qs.filter(rating__gte=min_rating)
return qsquery {
books(authorId: 1, publishedAfter: "2020-01-01", minRating: 4.0) {
title
rating
}
}Use annotations for database-level aggregations.
from django.db.models import Count, Avg
import strawberry_django
@strawberry_django.type(models.Author)
class Author:
id: auto
name: auto
book_count: int = strawberry_django.field(annotate={"book_count": Count("books")})
avg_book_rating: float = strawberry_django.field(
annotate={"avg_book_rating": Avg("books__rating")}
)query {
authors {
name
bookCount
avgBookRating
}
}- Always enable the Query Optimizer - Add
DjangoOptimizerExtension()to your schema - Paginate list queries - Prevent loading thousands of records
- Use filters and ordering - Let clients control what data they need
- Add appropriate indexes - Index fields used in filters and ordering
- Use custom resolvers sparingly - Default resolvers are optimized
- Leverage annotations - Perform calculations in the database
- Test query performance - Monitor SQL queries during development
import strawberry
import strawberry_django
from strawberry_django.optimizer import DjangoOptimizerExtension
from strawberry_django.pagination import OffsetPaginationInput
from . import models
from .types import Fruit, FruitFilter, FruitOrder
@strawberry.type
class Query:
# Single object query with PK filter
fruit: Fruit = strawberry_django.field()
# List query with filters, ordering, and pagination
@strawberry_django.field
def fruits(
self,
filters: FruitFilter | None = strawberry.UNSET,
order: FruitOrder | None = strawberry.UNSET,
pagination: OffsetPaginationInput | None = None,
) -> list[Fruit]:
qs = models.Fruit.objects.all()
# Filters and ordering are applied automatically
# when using strawberry_django.field
# Apply pagination
if pagination:
qs = qs[pagination.offset : pagination.offset + pagination.limit]
else:
qs = qs[:100] # Default limit
return qs
# Custom query with business logic
@strawberry_django.field
def featured_fruits(self) -> list[Fruit]:
return models.Fruit.objects.filter(is_featured=True, available=True).order_by(
"-created_at"
)[:10]
# Enable Query Optimizer
schema = strawberry.Schema(
query=Query,
extensions=[
DjangoOptimizerExtension(),
],
)query {
# Get single fruit
fruit(pk: "1") {
id
name
price
}
# List with filters and ordering
fruits(
filters: { name: { iContains: "berry" } }
order: { price: DESC }
pagination: { offset: 0, limit: 10 }
) {
id
name
price
}
# Custom query
featuredFruits {
id
name
}
}- Filtering - Comprehensive filtering guide
- Ordering - Sort and order results
- Pagination - Paginate large result sets
- Query Optimizer - Prevent N+1 queries
- Custom Resolvers - Advanced resolver patterns
- Relay - Relay-style connections and nodes