From d8d859d88d03257cdfed1982ad04c4d3a828edfb Mon Sep 17 00:00:00 2001 From: Soham Date: Wed, 12 Jun 2019 09:58:30 -0700 Subject: [PATCH 1/7] init --- graphene_django_extras/fields.py | 103 +++++++------------------------ graphene_django_extras/hints.py | 19 ++++++ graphene_django_extras/utils.py | 75 +++++++++++++--------- 3 files changed, 90 insertions(+), 107 deletions(-) create mode 100644 graphene_django_extras/hints.py diff --git a/graphene_django_extras/fields.py b/graphene_django_extras/fields.py index b80eb29..a3311f2 100644 --- a/graphene_django_extras/fields.py +++ b/graphene_django_extras/fields.py @@ -5,17 +5,14 @@ from graphene import Field, List, ID, Argument from graphene.types.structures import Structure from graphene_django.filter.utils import get_filtering_args_from_filterset -from graphene_django.utils import ( - maybe_queryset, - is_valid_django_model, - DJANGO_FILTER_INSTALLED, -) +from graphene_django.utils import maybe_queryset, is_valid_django_model, DJANGO_FILTER_INSTALLED +from graphql.execution.base import get_field_def from graphene_django_extras.settings import graphql_api_settings from graphene_django_extras.filters.filter import get_filterset_class from .base_types import DjangoListObjectBase from .paginations.pagination import BaseDjangoGraphqlPagination -from .utils import get_extra_filters, queryset_factory, get_related_fields, find_field +from .utils import get_extra_filters, queryset_factory, get_related_fields, find_field, get_type # *********************************************** # @@ -23,9 +20,7 @@ # *********************************************** # class DjangoObjectField(Field): def __init__(self, _type, *args, **kwargs): - kwargs["id"] = ID( - required=True, description="Django object unique identification field" - ) + kwargs["id"] = ID(required=True, description="Django object unique identification field") super(DjangoObjectField, self).__init__(_type, *args, **kwargs) @@ -51,13 +46,7 @@ def get_resolver(self, parent_resolver): # *********************************************** # class DjangoFilterListField(Field): def __init__( - self, - _type, - fields=None, - extra_filter_meta=None, - filterset_class=None, - *args, - **kwargs, + self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs ): if DJANGO_FILTER_INSTALLED: @@ -70,26 +59,16 @@ def __init__( meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset( - self.filterset_class, _type - ) + self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): self.filtering_args.update( - { - "id": Argument( - ID, description="Django object unique identification field" - ) - } + {"id": Argument(ID, description="Django object unique identification field")} ) kwargs["args"].update( - { - "id": Argument( - ID, description="Django object unique identification field" - ) - } + {"id": Argument(ID, description="Django object unique identification field")} ) if not kwargs.get("description", None): @@ -115,24 +94,18 @@ def list_resolver(manager, filterset_class, filtering_args, root, info, **kwargs try: if filter_kwargs: qs = operator.attrgetter( - "{}.filter".format( - getattr(field, "related_name", None) or field.name - ) + "{}.filter".format(getattr(field, "related_name", None) or field.name) )(root)(**filter_kwargs) else: qs = operator.attrgetter( - "{}.all".format( - getattr(field, "related_name", None) or field.name - ) + "{}.all".format(getattr(field, "related_name", None) or field.name) )(root)() except AttributeError: qs = None if qs is None: - qs = queryset_factory(manager, info.field_asts, info.fragments, **kwargs) - qs = filterset_class( - data=filter_kwargs, queryset=qs, request=info.context - ).qs + qs = queryset_factory(manager, info, **kwargs) + qs = filterset_class(data=filter_kwargs, queryset=qs, request=info.context).qs if root and is_valid_django_model(root._meta.model): extra_filters = get_extra_filters(root, manager.model) @@ -161,7 +134,7 @@ def __init__( extra_filter_meta=None, filterset_class=None, *args, - **kwargs, + **kwargs ): _fields = _type._meta.filter_fields @@ -174,26 +147,16 @@ def __init__( filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset( - self.filterset_class, _type - ) + self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): self.filtering_args.update( - { - "id": Argument( - ID, description="Django object unique identification field" - ) - } + {"id": Argument(ID, description="Django object unique identification field")} ) kwargs["args"].update( - { - "id": Argument( - ID, description="Django object unique identification field" - ) - } + {"id": Argument(ID, description="Django object unique identification field")} ) pagination = pagination or graphql_api_settings.DEFAULT_PAGINATION_CLASS() @@ -211,22 +174,16 @@ def __init__( if not kwargs.get("description", None): kwargs["description"] = "{} list".format(_type._meta.model.__name__) - super(DjangoFilterPaginateListField, self).__init__( - List(_type), *args, **kwargs - ) + super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs) @property def model(self): return self.type.of_type._meta.node._meta.model - def get_queryset(self, manager, info, **kwargs): - return queryset_factory(manager, info.field_asts, info.fragments, **kwargs) + def list_resolver(self, manager, filterset_class, filtering_args, root, info, **kwargs): - def list_resolver( - self, manager, filterset_class, filtering_args, root, info, **kwargs - ): filter_kwargs = {k: v for k, v in kwargs.items() if k in filtering_args} - qs = self.get_queryset(manager, info, **kwargs) + qs = queryset_factory(manager, info, **kwargs) qs = filterset_class(data=filter_kwargs, queryset=qs, request=info.context).qs if root and is_valid_django_model(root._meta.model): @@ -252,13 +209,7 @@ def get_resolver(self, parent_resolver): class DjangoListObjectField(Field): def __init__( - self, - _type, - fields=None, - extra_filter_meta=None, - filterset_class=None, - *args, - **kwargs, + self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs ): if DJANGO_FILTER_INSTALLED: @@ -273,17 +224,13 @@ def __init__( filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset( - self.filterset_class, _type - ) + self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): id_description = "Django object unique identification field" - self.filtering_args.update( - {"id": Argument(ID, description=id_description)} - ) + self.filtering_args.update({"id": Argument(ID, description=id_description)}) kwargs["args"].update({"id": Argument(ID, description=id_description)}) if not kwargs.get("description", None): @@ -295,11 +242,9 @@ def __init__( def model(self): return self.type._meta.model - def list_resolver( - self, manager, filterset_class, filtering_args, root, info, **kwargs - ): + def list_resolver(self, manager, filterset_class, filtering_args, root, info, **kwargs): - qs = queryset_factory(manager, info.field_asts, info.fragments, **kwargs) + qs = queryset_factory(manager, info, **kwargs) filter_kwargs = {k: v for k, v in kwargs.items() if k in filtering_args} diff --git a/graphene_django_extras/hints.py b/graphene_django_extras/hints.py new file mode 100644 index 0000000..30e572e --- /dev/null +++ b/graphene_django_extras/hints.py @@ -0,0 +1,19 @@ +__all__ = ["OptimizationHints", "resolver_hints"] + + +class OptimizationHints(object): + def __init__(self, model_field=None, select_related=None, prefetch_related=None, only=None): + self.model_field = model_field + self.prefetch_related = prefetch_related if prefetch_related else [] + self.select_related = select_related if select_related else [] + self.only = only if only else [] + + +def resolver_hints(*args, **kwargs): + optimization_hints = OptimizationHints(*args, **kwargs) + + def apply_resolver_hints(resolver): + resolver.optimization_hints = optimization_hints + return resolver + + return apply_resolver_hints diff --git a/graphene_django_extras/utils.py b/graphene_django_extras/utils.py index 8a915c4..54e708c 100644 --- a/graphene_django_extras/utils.py +++ b/graphene_django_extras/utils.py @@ -8,15 +8,10 @@ from django.apps import apps from django.contrib.contenttypes.fields import GenericForeignKey, GenericRel from django.core.exceptions import ValidationError, ImproperlyConfigured -from django.db.models import ( - NOT_PROVIDED, - QuerySet, - Manager, - Model, - ManyToOneRel, - ManyToManyRel, -) +from django.db.models import NOT_PROVIDED, QuerySet, Manager, Model, ManyToOneRel, ManyToManyRel from django.db.models.base import ModelBase +from graphql import ResolveInfo +from graphql.execution.base import get_field_def from graphene.utils.str_converters import to_snake_case from graphene_django.utils import is_valid_django_model from graphql import GraphQLList, GraphQLNonNull @@ -92,9 +87,7 @@ def get_model_fields(model): reverse_fields = list(get_reverse_fields(model)) exclude_fields = [field[1] for field in reverse_fields] - local_fields = [ - (field.name, field) for field in all_fields_list if field not in exclude_fields - ] + local_fields = [(field.name, field) for field in all_fields_list if field not in exclude_fields] all_fields = local_fields + reverse_fields @@ -120,7 +113,7 @@ def get_obj(app_label, model_name, object_id): except model.DoesNotExist: return None - except LookupError: + except LookupError as e: pass except ValidationError as e: raise ValidationError(e.__str__()) @@ -155,7 +148,7 @@ def create_obj(django_model, new_obj_key=None, *args, **kwargs): new_obj.full_clean() new_obj.save() return new_obj - except LookupError: + except LookupError as e: pass except ValidationError as e: raise ValidationError(e.__str__()) @@ -174,9 +167,7 @@ def clean_dict(d): return d if isinstance(d, list): return [v for v in (clean_dict(v) for v in d) if v] - return OrderedDict( - [(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v] - ) + return OrderedDict([(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v]) def get_type(_type): @@ -188,6 +179,7 @@ def get_type(_type): def get_fields(info): fragments = info.fragments field_asts = info.field_asts[0].selection_set.selections + _type = get_type(info.return_type) for field_ast in field_asts: field_name = field_ast.name.value @@ -203,7 +195,7 @@ def is_required(field): try: blank = getattr(field, "blank", getattr(field, "field", None)) default = getattr(field, "default", getattr(field, "field", None)) - # null = getattr(field, "null", getattr(field, "field", None)) + null = getattr(field, "null", getattr(field, "field", None)) if blank is None: blank = True @@ -287,19 +279,22 @@ def get_related_fields(model): def find_field(field, fields_dict): - temp = fields_dict.get( - field.name.value, fields_dict.get(to_snake_case(field.name.value), None) - ) + temp = fields_dict.get(field.name.value, fields_dict.get(to_snake_case(field.name.value), None)) return temp def recursive_params( - selection_set, fragments, available_related_fields, select_related, prefetch_related + root_info, + current_parent_type, + selection_set, + fragments, + available_related_fields, + select_related, + prefetch_related, ): for field in selection_set.selections: - if isinstance(field, FragmentSpread) and fragments: a, b = recursive_params( fragments[field.name.value].selection_set, @@ -314,6 +309,7 @@ def recursive_params( if isinstance(field, InlineFragment): a, b = recursive_params( + root_info, field.selection_set, fragments, available_related_fields, @@ -324,9 +320,24 @@ def recursive_params( [prefetch_related.append(x) for x in b if x not in prefetch_related] continue + field_def = get_field_def(root_info.schema, current_parent_type, field.name.value) + field_type = get_type(field_def.type) + + optimization_hints = getattr(field_def.resolver, "optimization_hints", None) + if optimization_hints: + [ + select_related.append(x) + for x in optimization_hints.select_related + if x not in select_related + ] + [ + prefetch_related.append(x) + for x in optimization_hints.prefetch_related + if x not in prefetch_related + ] + temp = available_related_fields.get( - field.name.value, - available_related_fields.get(to_snake_case(field.name.value), None), + field.name.value, available_related_fields.get(to_snake_case(field.name.value), None) ) if temp and temp.name not in [prefetch_related + select_related]: @@ -336,6 +347,8 @@ def recursive_params( select_related.append(temp.name) elif getattr(field, "selection_set", None): a, b = recursive_params( + root_info, + field_type, field.selection_set, fragments, available_related_fields, @@ -348,7 +361,10 @@ def recursive_params( return select_related, prefetch_related -def queryset_factory(manager, fields_asts=None, fragments=None, **kwargs): +def queryset_factory(manager, info, **kwargs): + + fields_asts = info.field_asts + fragments = info.fragments select_related = [] prefetch_related = [] @@ -357,15 +373,18 @@ def queryset_factory(manager, fields_asts=None, fragments=None, **kwargs): for f in kwargs.keys(): temp = available_related_fields.get(f.split("__", 1)[0], None) if temp: - if ( - temp.many_to_many or temp.one_to_many - ) and temp.name not in prefetch_related: + if (temp.many_to_many or temp.one_to_many) and temp.name not in prefetch_related: prefetch_related.append(temp.name) else: select_related.append(temp.name) + base_field_def = get_field_def(info.schema, info.parent_type, info.field_name) + base_type = get_type(base_field_def.type) + if fields_asts: select_related, prefetch_related = recursive_params( + info, + base_type, fields_asts[0].selection_set, fragments, available_related_fields, From 7dbc61263598cca570aee731ab32b9c966c23bde Mon Sep 17 00:00:00 2001 From: Soham Date: Wed, 12 Jun 2019 10:03:12 -0700 Subject: [PATCH 2/7] small changes --- graphene_django_extras/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/graphene_django_extras/utils.py b/graphene_django_extras/utils.py index 54e708c..f1360f6 100644 --- a/graphene_django_extras/utils.py +++ b/graphene_django_extras/utils.py @@ -10,7 +10,6 @@ from django.core.exceptions import ValidationError, ImproperlyConfigured from django.db.models import NOT_PROVIDED, QuerySet, Manager, Model, ManyToOneRel, ManyToManyRel from django.db.models.base import ModelBase -from graphql import ResolveInfo from graphql.execution.base import get_field_def from graphene.utils.str_converters import to_snake_case from graphene_django.utils import is_valid_django_model @@ -179,7 +178,6 @@ def get_type(_type): def get_fields(info): fragments = info.fragments field_asts = info.field_asts[0].selection_set.selections - _type = get_type(info.return_type) for field_ast in field_asts: field_name = field_ast.name.value @@ -195,7 +193,7 @@ def is_required(field): try: blank = getattr(field, "blank", getattr(field, "field", None)) default = getattr(field, "default", getattr(field, "field", None)) - null = getattr(field, "null", getattr(field, "field", None)) + # null = getattr(field, "null", getattr(field, "field", None)) if blank is None: blank = True From b6a6088667a703f4b3ce022c55299d7e0a7019d6 Mon Sep 17 00:00:00 2001 From: Soham Date: Mon, 17 Jun 2019 12:25:20 -0700 Subject: [PATCH 3/7] undo black --- graphene_django_extras/fields.py | 95 +++++++++++++++++++++++++------- graphene_django_extras/hints.py | 6 +- graphene_django_extras/utils.py | 72 +++++++++++++----------- 3 files changed, 118 insertions(+), 55 deletions(-) diff --git a/graphene_django_extras/fields.py b/graphene_django_extras/fields.py index a3311f2..1c9a76f 100644 --- a/graphene_django_extras/fields.py +++ b/graphene_django_extras/fields.py @@ -5,7 +5,11 @@ from graphene import Field, List, ID, Argument from graphene.types.structures import Structure from graphene_django.filter.utils import get_filtering_args_from_filterset -from graphene_django.utils import maybe_queryset, is_valid_django_model, DJANGO_FILTER_INSTALLED +from graphene_django.utils import ( + maybe_queryset, + is_valid_django_model, + DJANGO_FILTER_INSTALLED, +) from graphql.execution.base import get_field_def from graphene_django_extras.settings import graphql_api_settings @@ -20,7 +24,9 @@ # *********************************************** # class DjangoObjectField(Field): def __init__(self, _type, *args, **kwargs): - kwargs["id"] = ID(required=True, description="Django object unique identification field") + kwargs["id"] = ID( + required=True, description="Django object unique identification field" + ) super(DjangoObjectField, self).__init__(_type, *args, **kwargs) @@ -46,7 +52,13 @@ def get_resolver(self, parent_resolver): # *********************************************** # class DjangoFilterListField(Field): def __init__( - self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs + self, + _type, + fields=None, + extra_filter_meta=None, + filterset_class=None, + *args, + **kwargs, ): if DJANGO_FILTER_INSTALLED: @@ -59,16 +71,26 @@ def __init__( meta.update(extra_filter_meta) filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) + self.filtering_args = get_filtering_args_from_filterset( + self.filterset_class, _type + ) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): self.filtering_args.update( - {"id": Argument(ID, description="Django object unique identification field")} + { + "id": Argument( + ID, description="Django object unique identification field" + ) + } ) kwargs["args"].update( - {"id": Argument(ID, description="Django object unique identification field")} + { + "id": Argument( + ID, description="Django object unique identification field" + ) + } ) if not kwargs.get("description", None): @@ -94,18 +116,24 @@ def list_resolver(manager, filterset_class, filtering_args, root, info, **kwargs try: if filter_kwargs: qs = operator.attrgetter( - "{}.filter".format(getattr(field, "related_name", None) or field.name) + "{}.filter".format( + getattr(field, "related_name", None) or field.name + ) )(root)(**filter_kwargs) else: qs = operator.attrgetter( - "{}.all".format(getattr(field, "related_name", None) or field.name) + "{}.all".format( + getattr(field, "related_name", None) or field.name + ) )(root)() except AttributeError: qs = None if qs is None: qs = queryset_factory(manager, info, **kwargs) - qs = filterset_class(data=filter_kwargs, queryset=qs, request=info.context).qs + qs = filterset_class( + data=filter_kwargs, queryset=qs, request=info.context + ).qs if root and is_valid_django_model(root._meta.model): extra_filters = get_extra_filters(root, manager.model) @@ -134,7 +162,7 @@ def __init__( extra_filter_meta=None, filterset_class=None, *args, - **kwargs + **kwargs, ): _fields = _type._meta.filter_fields @@ -147,16 +175,26 @@ def __init__( filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) + self.filtering_args = get_filtering_args_from_filterset( + self.filterset_class, _type + ) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): self.filtering_args.update( - {"id": Argument(ID, description="Django object unique identification field")} + { + "id": Argument( + ID, description="Django object unique identification field" + ) + } ) kwargs["args"].update( - {"id": Argument(ID, description="Django object unique identification field")} + { + "id": Argument( + ID, description="Django object unique identification field" + ) + } ) pagination = pagination or graphql_api_settings.DEFAULT_PAGINATION_CLASS() @@ -174,14 +212,17 @@ def __init__( if not kwargs.get("description", None): kwargs["description"] = "{} list".format(_type._meta.model.__name__) - super(DjangoFilterPaginateListField, self).__init__(List(_type), *args, **kwargs) + super(DjangoFilterPaginateListField, self).__init__( + List(_type), *args, **kwargs + ) @property def model(self): return self.type.of_type._meta.node._meta.model - def list_resolver(self, manager, filterset_class, filtering_args, root, info, **kwargs): - + def list_resolver( + self, manager, filterset_class, filtering_args, root, info, **kwargs + ): filter_kwargs = {k: v for k, v in kwargs.items() if k in filtering_args} qs = queryset_factory(manager, info, **kwargs) qs = filterset_class(data=filter_kwargs, queryset=qs, request=info.context).qs @@ -209,7 +250,13 @@ def get_resolver(self, parent_resolver): class DjangoListObjectField(Field): def __init__( - self, _type, fields=None, extra_filter_meta=None, filterset_class=None, *args, **kwargs + self, + _type, + fields=None, + extra_filter_meta=None, + filterset_class=None, + *args, + **kwargs, ): if DJANGO_FILTER_INSTALLED: @@ -224,13 +271,17 @@ def __init__( filterset_class = filterset_class or _type._meta.filterset_class self.filterset_class = get_filterset_class(filterset_class, **meta) - self.filtering_args = get_filtering_args_from_filterset(self.filterset_class, _type) + self.filtering_args = get_filtering_args_from_filterset( + self.filterset_class, _type + ) kwargs.setdefault("args", {}) kwargs["args"].update(self.filtering_args) if "id" not in kwargs["args"].keys(): id_description = "Django object unique identification field" - self.filtering_args.update({"id": Argument(ID, description=id_description)}) + self.filtering_args.update( + {"id": Argument(ID, description=id_description)} + ) kwargs["args"].update({"id": Argument(ID, description=id_description)}) if not kwargs.get("description", None): @@ -242,7 +293,9 @@ def __init__( def model(self): return self.type._meta.model - def list_resolver(self, manager, filterset_class, filtering_args, root, info, **kwargs): + def list_resolver( + self, manager, filterset_class, filtering_args, root, info, **kwargs + ): qs = queryset_factory(manager, info, **kwargs) @@ -263,4 +316,4 @@ def get_resolver(self, parent_resolver): self.type._meta.model._default_manager, self.filterset_class, self.filtering_args, - ) + ) \ No newline at end of file diff --git a/graphene_django_extras/hints.py b/graphene_django_extras/hints.py index 30e572e..334f5e3 100644 --- a/graphene_django_extras/hints.py +++ b/graphene_django_extras/hints.py @@ -4,9 +4,9 @@ class OptimizationHints(object): def __init__(self, model_field=None, select_related=None, prefetch_related=None, only=None): self.model_field = model_field - self.prefetch_related = prefetch_related if prefetch_related else [] - self.select_related = select_related if select_related else [] - self.only = only if only else [] + self.prefetch_related = set(prefetch_related) if prefetch_related else set() + self.select_related = set(select_related) if select_related else set() + self.only = set(only) if only else set() def resolver_hints(*args, **kwargs): diff --git a/graphene_django_extras/utils.py b/graphene_django_extras/utils.py index f1360f6..1287386 100644 --- a/graphene_django_extras/utils.py +++ b/graphene_django_extras/utils.py @@ -8,7 +8,14 @@ from django.apps import apps from django.contrib.contenttypes.fields import GenericForeignKey, GenericRel from django.core.exceptions import ValidationError, ImproperlyConfigured -from django.db.models import NOT_PROVIDED, QuerySet, Manager, Model, ManyToOneRel, ManyToManyRel +from django.db.models import ( + NOT_PROVIDED, + QuerySet, + Manager, + Model, + ManyToOneRel, + ManyToManyRel, +) from django.db.models.base import ModelBase from graphql.execution.base import get_field_def from graphene.utils.str_converters import to_snake_case @@ -86,7 +93,9 @@ def get_model_fields(model): reverse_fields = list(get_reverse_fields(model)) exclude_fields = [field[1] for field in reverse_fields] - local_fields = [(field.name, field) for field in all_fields_list if field not in exclude_fields] + local_fields = [ + (field.name, field) for field in all_fields_list if field not in exclude_fields + ] all_fields = local_fields + reverse_fields @@ -112,7 +121,7 @@ def get_obj(app_label, model_name, object_id): except model.DoesNotExist: return None - except LookupError as e: + except LookupError: pass except ValidationError as e: raise ValidationError(e.__str__()) @@ -147,7 +156,7 @@ def create_obj(django_model, new_obj_key=None, *args, **kwargs): new_obj.full_clean() new_obj.save() return new_obj - except LookupError as e: + except LookupError: pass except ValidationError as e: raise ValidationError(e.__str__()) @@ -166,7 +175,9 @@ def clean_dict(d): return d if isinstance(d, list): return [v for v in (clean_dict(v) for v in d) if v] - return OrderedDict([(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v]) + return OrderedDict( + [(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v] + ) def get_type(_type): @@ -193,7 +204,7 @@ def is_required(field): try: blank = getattr(field, "blank", getattr(field, "field", None)) default = getattr(field, "default", getattr(field, "field", None)) - # null = getattr(field, "null", getattr(field, "field", None)) + # null = getattr(field, "null", getattr(field, "field", None)) if blank is None: blank = True @@ -277,24 +288,31 @@ def get_related_fields(model): def find_field(field, fields_dict): - temp = fields_dict.get(field.name.value, fields_dict.get(to_snake_case(field.name.value), None)) + temp = fields_dict.get( + field.name.value, fields_dict.get(to_snake_case(field.name.value), None) + ) return temp def recursive_params( - root_info, - current_parent_type, - selection_set, - fragments, - available_related_fields, - select_related, - prefetch_related, + root_info, + current_parent_type, + selection_set, + fragments, + available_related_fields, + select_related, + prefetch_related, ): for field in selection_set.selections: + field_def = get_field_def(root_info.schema, current_parent_type, field.name.value) + field_type = get_type(field_def.type) + if isinstance(field, FragmentSpread) and fragments: a, b = recursive_params( + root_info, + field_type, fragments[field.name.value].selection_set, fragments, available_related_fields, @@ -308,6 +326,7 @@ def recursive_params( if isinstance(field, InlineFragment): a, b = recursive_params( root_info, + field_type, field.selection_set, fragments, available_related_fields, @@ -318,24 +337,14 @@ def recursive_params( [prefetch_related.append(x) for x in b if x not in prefetch_related] continue - field_def = get_field_def(root_info.schema, current_parent_type, field.name.value) - field_type = get_type(field_def.type) - optimization_hints = getattr(field_def.resolver, "optimization_hints", None) if optimization_hints: - [ - select_related.append(x) - for x in optimization_hints.select_related - if x not in select_related - ] - [ - prefetch_related.append(x) - for x in optimization_hints.prefetch_related - if x not in prefetch_related - ] + select_related = sorted(set(select_related) | optimization_hints.select_related) + prefetch_related = sorted(set(prefetch_related) | optimization_hints.prefetch_related) temp = available_related_fields.get( - field.name.value, available_related_fields.get(to_snake_case(field.name.value), None) + field.name.value, + available_related_fields.get(to_snake_case(field.name.value), None), ) if temp and temp.name not in [prefetch_related + select_related]: @@ -360,7 +369,6 @@ def recursive_params( def queryset_factory(manager, info, **kwargs): - fields_asts = info.field_asts fragments = info.fragments @@ -371,7 +379,9 @@ def queryset_factory(manager, info, **kwargs): for f in kwargs.keys(): temp = available_related_fields.get(f.split("__", 1)[0], None) if temp: - if (temp.many_to_many or temp.one_to_many) and temp.name not in prefetch_related: + if ( + temp.many_to_many or temp.one_to_many + ) and temp.name not in prefetch_related: prefetch_related.append(temp.name) else: select_related.append(temp.name) @@ -408,4 +418,4 @@ def parse_validation_exc(validation_exc): for exc in value: errors_list.append({"field": key, "messages": exc.messages}) - return errors_list + return errors_list \ No newline at end of file From 0bc8c18d47ae17e6c6d8a3d2e6960b4d90f3c9ad Mon Sep 17 00:00:00 2001 From: Soham Date: Mon, 17 Jun 2019 12:26:09 -0700 Subject: [PATCH 4/7] line end --- graphene_django_extras/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene_django_extras/utils.py b/graphene_django_extras/utils.py index 1287386..ddc8a21 100644 --- a/graphene_django_extras/utils.py +++ b/graphene_django_extras/utils.py @@ -418,4 +418,4 @@ def parse_validation_exc(validation_exc): for exc in value: errors_list.append({"field": key, "messages": exc.messages}) - return errors_list \ No newline at end of file + return errors_list From 48c99835c233e3ae10a9330652dfc392083717c2 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 20 Aug 2019 18:35:26 -0700 Subject: [PATCH 5/7] the current resolver_hints might not work --- graphene_django_extras/hints.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/graphene_django_extras/hints.py b/graphene_django_extras/hints.py index 334f5e3..2c96adb 100644 --- a/graphene_django_extras/hints.py +++ b/graphene_django_extras/hints.py @@ -11,9 +11,9 @@ def __init__(self, model_field=None, select_related=None, prefetch_related=None, def resolver_hints(*args, **kwargs): optimization_hints = OptimizationHints(*args, **kwargs) - - def apply_resolver_hints(resolver): - resolver.optimization_hints = optimization_hints - return resolver - - return apply_resolver_hints + def apply_resolver_hints(function): + def wrapper(resolver, *args, **kwargs): + resolver.optimization_hints = optimization_hints + return function(resolver, *args, **kwargs) + return wrapper + return apply_resolver_hints \ No newline at end of file From cf1e4fc4d9944527e3b3d0f41cc9a539ff8e49f8 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 21 Aug 2019 12:37:58 -0700 Subject: [PATCH 6/7] fix parameter error --- graphene_django_extras/fields.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphene_django_extras/fields.py b/graphene_django_extras/fields.py index 1c9a76f..c5a1c91 100644 --- a/graphene_django_extras/fields.py +++ b/graphene_django_extras/fields.py @@ -58,7 +58,7 @@ def __init__( extra_filter_meta=None, filterset_class=None, *args, - **kwargs, + **kwargs ): if DJANGO_FILTER_INSTALLED: @@ -162,7 +162,7 @@ def __init__( extra_filter_meta=None, filterset_class=None, *args, - **kwargs, + **kwargs ): _fields = _type._meta.filter_fields @@ -256,7 +256,7 @@ def __init__( extra_filter_meta=None, filterset_class=None, *args, - **kwargs, + **kwargs ): if DJANGO_FILTER_INSTALLED: From d0173dd740410a5e6b0a0f08b599ecb208fdc031 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 21 Aug 2019 14:28:19 -0700 Subject: [PATCH 7/7] change the decorator back --- graphene_django_extras/hints.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/graphene_django_extras/hints.py b/graphene_django_extras/hints.py index 2c96adb..334f5e3 100644 --- a/graphene_django_extras/hints.py +++ b/graphene_django_extras/hints.py @@ -11,9 +11,9 @@ def __init__(self, model_field=None, select_related=None, prefetch_related=None, def resolver_hints(*args, **kwargs): optimization_hints = OptimizationHints(*args, **kwargs) - def apply_resolver_hints(function): - def wrapper(resolver, *args, **kwargs): - resolver.optimization_hints = optimization_hints - return function(resolver, *args, **kwargs) - return wrapper - return apply_resolver_hints \ No newline at end of file + + def apply_resolver_hints(resolver): + resolver.optimization_hints = optimization_hints + return resolver + + return apply_resolver_hints