{"id":7276,"library":"graphene-django-optimizer","title":"Graphene-Django Optimizer","description":"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.","status":"active","version":"0.10.0","language":"en","source_language":"en","source_url":"https://github.com/tfoxy/graphene-django-optimizer","tags":["graphene","django","graphql","optimization","database","orm","n+1"],"install":[{"cmd":"pip install graphene-django-optimizer","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core ORM and web framework. Requires >=2.2,<5.0.","package":"Django","optional":false},{"reason":"Connects Graphene with Django models. Requires >=2.15,<4.0.","package":"graphene-django","optional":false},{"reason":"Core GraphQL library. Requires >=2.1,<4.0.","package":"graphene","optional":false},{"reason":"Low-level GraphQL implementation. Requires >=2.1,<4.0.","package":"graphql-core","optional":false}],"imports":[{"symbol":"DjangoOptimizerExtension","correct":"from graphene_django_optimizer import DjangoOptimizerExtension"},{"symbol":"QueryOptimizer","correct":"from graphene_django_optimizer import QueryOptimizer"},{"note":"The `optimize` decorator is directly available from the top-level package.","wrong":"from graphene_django_optimizer.resolver import optimize","symbol":"optimize","correct":"from graphene_django_optimizer import optimize"}],"quickstart":{"code":"import graphene\nfrom django.db import models\nfrom django.conf import settings\nfrom graphene_django.types import DjangoObjectType\nfrom graphene_django_optimizer import DjangoOptimizerExtension\n\n# Minimal Django setup required for DjangoObjectType to function\n# In a real Django project, these settings would be in your settings.py\nif not settings.configured:\n    settings.configure(\n        INSTALLED_APPS=['graphene_django', 'graphene_django_optimizer', 'myapp'],\n        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},\n        GRAPHENE={'EXTENSIONS': [DjangoOptimizerExtension]}, # Enable globally via settings\n        # Needed for Django models to be discovered\n        MIGRATION_MODULES={'myapp': None}\n    )\n    import django\n    django.setup()\n\n# Define a simple Django model\nclass Author(models.Model):\n    name = models.CharField(max_length=100)\n\n    class Meta:\n        app_label = 'myapp' # Critical for in-memory Django setup\n\nclass Book(models.Model):\n    title = models.CharField(max_length=200)\n    author_obj = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')\n    \n    class Meta:\n        app_label = 'myapp'\n\n# Define Graphene types for the models\nclass AuthorType(DjangoObjectType):\n    class Meta:\n        model = Author\n        fields = (\"id\", \"name\", \"books\")\n\nclass BookType(DjangoObjectType):\n    class Meta:\n        model = Book\n        fields = (\"id\", \"title\", \"author_obj\")\n\n# Define a Graphene Query\nclass Query(graphene.ObjectType):\n    all_authors = graphene.List(AuthorType)\n    all_books = graphene.List(BookType)\n\n    def resolve_all_authors(root, info):\n        # The DjangoOptimizerExtension will automatically apply select_related/prefetch_related\n        # for related fields requested in the GraphQL query (e.g., 'books' on AuthorType)\n        return Author.objects.all()\n    \n    def resolve_all_books(root, info):\n        return Book.objects.all()\n\n# Create the Graphene Schema\n# The extension is enabled via settings.GRAPHENE['EXTENSIONS']\nschema = graphene.Schema(query=Query)\n\n# --- Example Usage (for demonstration, not typically part of quickstart.code) ---\n\n# Create some dummy data\nauthor1 = Author.objects.create(name=\"Douglas Adams\")\nauthor2 = Author.objects.create(name=\"Jane Austen\")\nBook.objects.create(title=\"The Hitchhiker's Guide to the Galaxy\", author_obj=author1)\nBook.objects.create(title=\"Pride and Prejudice\", author_obj=author2)\nBook.objects.create(title=\"The Restaurant at the End of the Universe\", author_obj=author1)\n\n# Define a GraphQL query that would typically cause N+1 without optimization\nquery = \"\"\"\n    query {\n        allBooks {\n            id\n            title\n            author_obj {\n                name\n            }\n        }\n    }\n\"\"\"\n\n# Execute the query\nresult = schema.execute(query)\n\n# Check for errors and data (in a real scenario, you'd inspect logs for N+1)\nassert not result.errors\nassert len(result.data['allBooks']) == 3\nassert result.data['allBooks'][0]['author_obj']['name'] == 'Douglas Adams'\nprint(\"Optimization enabled successfully! Check your database query logs if available.\")","lang":"python","description":"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."},"warnings":[{"fix":"For Graphene 3 projects, upgrade `graphene-django-optimizer` to `^0.9.0`. For Graphene 2 projects, downgrade `graphene-django-optimizer` to `~=0.8.0`.","message":"Version 0.9.0 introduced support for Graphene 3, simultaneously dropping support for Graphene 2. If you are using Graphene 2, you must pin your `graphene-django-optimizer` version to `<0.9.0` (e.g., use `~=0.8.0`).","severity":"breaking","affected_versions":">=0.9.0"},{"fix":"Ensure you are using `graphene-django-optimizer >= 0.10.0` when your project includes `graphql-core >= 3.2`.","message":"Version 0.10.0 fixed a compatibility issue with `graphql-core v3.2`. If you are using `graphql-core >= 3.2` with `graphene-django-optimizer < 0.10.0`, you might encounter runtime errors or unexpected behavior.","severity":"gotcha","affected_versions":"<0.10.0 with graphql-core >=3.2"},{"fix":"Upgrade your Django installation to `2.2` or newer and Python to `3.6` or newer, or pin `graphene-django-optimizer` to an older compatible version if using legacy environments.","message":"Versions prior to 0.6.0 supported older Django and Python versions. Current versions (>=0.6.0) require Django `>=2.2` and Python `>=3.6`.","severity":"breaking","affected_versions":"<0.6.0"},{"fix":"Review custom resolvers to ensure they explicitly call `QueryOptimizer.optimize_query(queryset, info)` or are decorated with `@optimize` to prevent N+1 queries.","message":"Automatic optimization through `DjangoOptimizerExtension` only applies to fields resolved by `DjangoObjectType`'s default resolver. For custom resolvers, you must manually apply `QueryOptimizer.optimize_query(queryset, info)` or use the `@optimize` decorator.","severity":"gotcha","affected_versions":"*"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"If using Graphene 2, pin `graphene-django-optimizer` to `<0.9.0`. If you intend to use Graphene 3, ensure your Graphene installation is `graphene >= 3.0`.","cause":"Attempting to pass `extensions` argument to `graphene.Schema` constructor when using Graphene 2 with `graphene-django-optimizer >= 0.9.0` (which expects Graphene 3).","error":"TypeError: __init__() got an unexpected keyword argument 'extensions'"},{"fix":"Verify `DjangoOptimizerExtension` is present in `settings.GRAPHENE['EXTENSIONS']`. For custom resolvers, ensure `QueryOptimizer.optimize_query(queryset, info)` is called with the base queryset before returning, or use the `@optimize` decorator.","cause":"The `DjangoOptimizerExtension` is not correctly configured in `settings.GRAPHENE['EXTENSIONS']`, or `QueryOptimizer.optimize_query` is not called for custom resolvers.","error":"AttributeError: 'Manager' object has no attribute 'select_related' or 'prefetch_related' (or similar N+1 query warning)"},{"fix":"Run `pip install graphene-django-optimizer` in your project's virtual environment. Ensure your IDE or server is using the correct Python interpreter.","cause":"The `graphene-django-optimizer` package is not installed or the Python environment is incorrect.","error":"No module named 'graphene_django_optimizer'"},{"fix":"Ensure the GraphQL schema execution correctly serializes the output. In a Django project, this typically happens automatically within `graphene_django.views.GraphQLView`. When testing, use `schema.execute(query).data` to get the dict representation.","cause":"This error isn't directly from `graphene-django-optimizer`, but often occurs when trying to debug optimized queries that return Django QuerySet objects directly without proper serialization or when running Graphene outside a Django request context.","error":"TypeError: Object of type Book is not JSON serializable (when debugging/printing query result)"}]}