Skip to main content

Automatic query optimization for django and strawberry-graphql

Project description

strawberry-django-optimizer

PyPI version python version django version

Optimize queries executed by strawberry automatically, using select_related , prefetch_related and only methods of Django QuerySet.

This package is heavily based on graphene-django-optimizer which is intended for use with graphene-django.

Install

pip install strawberry-django-optimizer

Usage

Having the following models based on the strawberry-graphql-django docs:

# models.py
from django.db import models


class Fruit(models.Model):
    name = models.CharField(max_length=20)
    color = models.ForeignKey('Color', blank=True, null=True,
                              related_name='fruits', on_delete=models.CASCADE)


class Color(models.Model):
    name = models.CharField(max_length=20)

And the following schema:

# schema.py
import strawberry
from typing import List
from strawberry.django import auto
from strawberry_django_optimizer import optimized_django_field
from fruits import models


@strawberry.django.type(models.Fruit)
class Fruit:
    id: auto
    name: auto
    color: 'Color'


@strawberry.django.type(models.Color)
class Color:
    id: auto
    name: auto
    fruits: List[Fruit]


@strawberry.type
class Query:
    fruits: List[Fruit] = optimized_django_field()

The following graphql query would cause n + 1 DB queries:

query Fruit {
    fruits {
        id
        name
        color {
            id
            name
        }
    }
}

Since optimized_django_field was used instead of strawberry.django.field the queryset is automatically optimized.

# optimized queryset:
Fruits.objects.select_related('color').only('id', 'name', 'color__id', 'color__name')

Reverse ForeignKey relations also are automatically optimized with prefetch_related:

query Colors {
    colors {
        id
        name
        fruits {
            id
            name
        }
    }
}
# optimized queryset:
Color.objects.only('id', 'name', 'color').prefetch_related(
    Prefetch('fruits', queryset=Fruit.objects.only('id', 'name'))
)

Advanced usage

Use resolver_hint for cases where only, select_related and prefetch_related optimizations can't be inferred automatically. To keep the only optimization when using custom resolver functions, resolver_hints must be used to declare all fields that are accessed or the only optimization will be disabled.

# schema.py
import strawberry
from strawberry.django import auto
from strawberry_django_optimizer import resolver_hints
from fruits import models


@strawberry.django.type(models.Fruit)
class Fruit:
    id: auto
    
    @resolver_hints(only=('name',))
    @strawberry.field
    def name_display(self) -> str:
        return f'My name is: {self.name}'

If the resolver function accesses a related field you can add an optimization hint for select_related:

# schema.py
import strawberry
from strawberry.django import auto
from strawberry_django_optimizer import resolver_hints
from fruits import models


@strawberry.django.type(models.Fruit)
class Fruit:
    id: auto
    
    @resolver_hints(
        select_related=('color',),
        only=('color__name',),
    )
    def color_display(self) -> str:
        return f'My color is: {self.color.name}'

Parameters for resolver_hint

Parameter Usage
model_field If the resolver returns a model field
only Declare all fields that the resolver accesses
select_related If the resolver uses related fields
prefetch_reltaed If the resolver uses related fields

Known issues (ToDo)

  • Inline Fragments can't be optimized
  • Interfaces and Unions are not supported

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for strawberry-django-optimizer, version 0.1.0
Filename, size File type Python version Upload date Hashes
Filename, size strawberry_django_optimizer-0.1.0-py3-none-any.whl (9.7 kB) File type Wheel Python version py3 Upload date Hashes View
Filename, size strawberry-django-optimizer-0.1.0.tar.gz (9.4 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Huawei Huawei PSF Sponsor Microsoft Microsoft PSF Sponsor NVIDIA NVIDIA PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page