Improved query optimizer

This commit is contained in:
Syrus Akbary 2015-12-09 18:54:06 -08:00
parent c87ad41cf8
commit 867f0698f0
3 changed files with 30 additions and 27 deletions

View File

@ -0,0 +1,28 @@
from functools import wraps
from graphql.core.utils.get_field_def import get_field_def
from graphql.core.type.definition import GraphQLList, GraphQLNonNull
def get_fields(info):
field_asts = info.field_asts[0].selection_set.selections
only_args = []
_type = info.return_type
if isinstance(_type, (GraphQLList, GraphQLNonNull)):
_type = _type.of_type
for field in field_asts:
field_def = get_field_def(info.schema, _type, field)
f = field_def.resolver
fetch_field = getattr(f, 'django_fetch_field', None)
if not fetch_field:
continue
only_args.append(fetch_field.attname)
return only_args
def fetch_only_required(f):
@wraps(f)
def wrapper(*args):
info = args[-1]
return f(*args).only(*get_fields(info))
return wrapper

View File

@ -12,7 +12,7 @@ from .utils import get_type_for_model
class DjangoField(Field): class DjangoField(Field):
def decorate_resolver(self, resolver): def decorate_resolver(self, resolver):
f = super(DjangoField, self).decorate_resolver(resolver) f = super(DjangoField, self).decorate_resolver(resolver)
setattr(f, 'django_fetch_field', self.field.name) setattr(f, 'django_fetch_field', self.field)
return f return f
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -1,41 +1,16 @@
from functools import wraps
from graphql.core.utils.get_field_def import get_field_def
import pytest import pytest
import graphene import graphene
from graphene.contrib.django import DjangoObjectType from graphene.contrib.django import DjangoObjectType
from graphql.core.type.definition import GraphQLList, GraphQLNonNull
from ..tests.models import Reporter from ..tests.models import Reporter
from ..debug.plugin import DjangoDebugPlugin from ..debug.plugin import DjangoDebugPlugin
from ..fetcher import fetch_only_required, get_fields
# from examples.starwars_django.models import Character # from examples.starwars_django.models import Character
pytestmark = pytest.mark.django_db pytestmark = pytest.mark.django_db
def get_fields(info):
field_asts = info.field_asts[0].selection_set.selections
only_args = []
_type = info.return_type
if isinstance(_type, (GraphQLList, GraphQLNonNull)):
_type = _type.of_type
for field in field_asts:
field_def = get_field_def(info.schema, _type, field)
f = field_def.resolver
fetch_field = getattr(f, 'django_fetch_field', None)
if fetch_field:
only_args.append(fetch_field)
return only_args
def fetch_only_required(f):
@wraps(f)
def wrapper(*args):
info = args[-1]
return f(*args).only(*get_fields(info))
return wrapper
def test_should_query_well(): def test_should_query_well():
r1 = Reporter(last_name='ABA') r1 = Reporter(last_name='ABA')