Optimize database access inside graphene queries.
Project description
graphene-django-optimizer
Optimize queries executed by graphene-django automatically, using select_related
, prefetch_related
and only
methods of Django QuerySet.
Install
pip install graphene-django-optimizer
Usage
Having the following schema based on the tutorial of graphene-django (notice the use of gql_optimizer
)
# cookbook/ingredients/schema.py
import graphene
from graphene_django.types import DjangoObjectType
import graphene_django_optimizer as gql_optimizer
from cookbook.ingredients.models import Category, Ingredient
class CategoryType(DjangoObjectType):
class Meta:
model = Category
class IngredientType(DjangoObjectType):
class Meta:
model = Ingredient
class Query(object):
all_categories = graphene.List(CategoryType)
all_ingredients = graphene.List(IngredientType)
def resolve_all_categories(root, info):
return gql_optimizer.query(Category.objects.all(), info)
def resolve_all_ingredients(root, info):
return gql_optimizer.query(Ingredient.objects.all(), info)
We will show some graphql queries and the queryset that will be executed.
Fetching all the ingredients with the related category:
{
all_ingredients {
id
name
category {
id
name
}
}
}
# optimized queryset:
ingredients = (
Ingredient.objects
.select_related('category')
.only('id', 'name', 'category__id', 'category__name')
)
Fetching all the categories with the related ingredients:
{
all_categories {
id
name
ingredients {
id
name
}
}
}
# optimized queryset:
categories = (
Category.objects
.only('id', 'name')
.prefetch_related(Prefetch(
'ingredients',
queryset=Ingredient.objects.only('id', 'name'),
))
)
Advanced usage
Sometimes we need to have a custom resolver function. In those cases, the field can't be auto optimized.
So we need to use gql_optimizer.resolver_hints
decorator to indicate the optimizations.
If the resolver returns a model field, we can use the model_field
argument:
import graphene
from graphene_django.types import DjangoObjectType
import graphene_django_optimizer as gql_optimizer
class ItemType(DjangoObjectType):
product = graphene.Field('ProductType')
@gql_optimizer.resolver_hints(
model_field='product',
)
def resolve_product(root, info):
# check if user have permission for seeing the product
if info.context.user.is_anonymous():
return None
return root.product
This will automatically optimize any subfield of product
.
Now, if the resolver uses related fields, you can use the select_related
argument:
import graphene
from graphene_django.types import DjangoObjectType
import graphene_django_optimizer as gql_optimizer
class ItemType(DjangoObjectType):
name = graphene.String()
@gql_optimizer.resolver_hints(
select_related=('product', 'shipping'),
only=('product__name', 'shipping__name'),
)
def resolve_name(root, info):
return '{} {}'.format(root.product.name, root.shipping.name)
Finally, if your field has an argument for filtering results,
you can use the prefetch_related
argument with a function
that returns a Prefetch
instance as the value.
from django.db.models import Prefetch
import graphene
from graphene_django.types import DjangoObjectType
import graphene_django_optimizer as gql_optimizer
class CartType(DjangoObjectType):
items = graphene.List(
'ItemType',
product_id=graphene.ID(),
)
@gql_optimizer.resolver_hints(
prefetch_related=lambda info, product_id: Prefetch(
'items',
queryset=gql_optimizer.query(Item.objects.filter(product_id=product_id), info),
to_attr='gql_product_id_' + product_id,
),
)
def resolve_items(root, info, product_id):
return getattr(root, 'gql_product_id_' + product_id)
With these hints, any field can be optimized.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for graphene-django-optimizer-0.3.6.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | f55adcb5452d6d65dfce4afa5de50f6d987bb84c5dd3ccdc89b0802662852b1b |
|
MD5 | 5e45b71daa6a92e1d636c343164da45d |
|
BLAKE2b-256 | 90d842fa25d278c48bbc38739a3cbf0b59f385242454da18ff9eb789b55d81ef |
Hashes for graphene_django_optimizer-0.3.6-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e3eafbcf343a9501ced71d0a8537dda2b1fe0d7bcf9c31bf0b371556d8ee4467 |
|
MD5 | 4b8379e972ddc4032b67ad894b0cc0a0 |
|
BLAKE2b-256 | 3bbab3c5a8aebe5f55ba6093e30d259cdf867a498a722f6f722e2518754a9ab3 |