Graphene-Django Optimizer

0.10.0 · active · verified Thu Apr 16

graphene-django-optimizer is a library for Graphene-Django that automatically optimizes database access (e.g., using `select_related`, `prefetch_related`) within GraphQL queries to mitigate N+1 query problems. Its current version is 0.10.0, and it follows a release cadence driven by new Graphene or Django versions and bug fixes, with a focus on supporting the latest major versions of its dependencies.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `graphene-django-optimizer` by adding `DjangoOptimizerExtension` to your `GRAPHENE['EXTENSIONS']` settings. This global setting ensures that all `DjangoObjectType` fields are automatically optimized, preventing N+1 queries for `select_related` and `prefetch_related` relationships specified in your GraphQL query. The example sets up a minimal Django environment and Graphene schema to illustrate usage.

import graphene
from django.db import models
from django.conf import settings
from graphene_django.types import DjangoObjectType
from graphene_django_optimizer import DjangoOptimizerExtension

# Minimal Django setup required for DjangoObjectType to function
# In a real Django project, these settings would be in your settings.py
if not settings.configured:
    settings.configure(
        INSTALLED_APPS=['graphene_django', 'graphene_django_optimizer', 'myapp'],
        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
        GRAPHENE={'EXTENSIONS': [DjangoOptimizerExtension]}, # Enable globally via settings
        # Needed for Django models to be discovered
        MIGRATION_MODULES={'myapp': None}
    )
    import django
    django.setup()

# Define a simple Django model
class Author(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        app_label = 'myapp' # Critical for in-memory Django setup

class Book(models.Model):
    title = models.CharField(max_length=200)
    author_obj = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
    
    class Meta:
        app_label = 'myapp'

# Define Graphene types for the models
class AuthorType(DjangoObjectType):
    class Meta:
        model = Author
        fields = ("id", "name", "books")

class BookType(DjangoObjectType):
    class Meta:
        model = Book
        fields = ("id", "title", "author_obj")

# Define a Graphene Query
class Query(graphene.ObjectType):
    all_authors = graphene.List(AuthorType)
    all_books = graphene.List(BookType)

    def resolve_all_authors(root, info):
        # The DjangoOptimizerExtension will automatically apply select_related/prefetch_related
        # for related fields requested in the GraphQL query (e.g., 'books' on AuthorType)
        return Author.objects.all()
    
    def resolve_all_books(root, info):
        return Book.objects.all()

# Create the Graphene Schema
# The extension is enabled via settings.GRAPHENE['EXTENSIONS']
schema = graphene.Schema(query=Query)

# --- Example Usage (for demonstration, not typically part of quickstart.code) ---

# Create some dummy data
author1 = Author.objects.create(name="Douglas Adams")
author2 = Author.objects.create(name="Jane Austen")
Book.objects.create(title="The Hitchhiker's Guide to the Galaxy", author_obj=author1)
Book.objects.create(title="Pride and Prejudice", author_obj=author2)
Book.objects.create(title="The Restaurant at the End of the Universe", author_obj=author1)

# Define a GraphQL query that would typically cause N+1 without optimization
query = """
    query {
        allBooks {
            id
            title
            author_obj {
                name
            }
        }
    }
"""

# Execute the query
result = schema.execute(query)

# Check for errors and data (in a real scenario, you'd inspect logs for N+1)
assert not result.errors
assert len(result.data['allBooks']) == 3
assert result.data['allBooks'][0]['author_obj']['name'] == 'Douglas Adams'
print("Optimization enabled successfully! Check your database query logs if available.")

view raw JSON →