diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-04-11 06:03:38 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-04-11 06:03:38 +0000 |
| commit | d79e2029b557887abb0506277790cfc849768aa6 (patch) | |
| tree | f93b54c47a3c3ceaacaafb5c33a8d50cc2c3175f | |
| parent | c013d7d6fa793ddd83a97c981a2502b4660a3844 (diff) | |
automatic import of python-graphene-django-optimizer
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-graphene-django-optimizer.spec | 711 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 713 insertions, 0 deletions
@@ -0,0 +1 @@ +/graphene-django-optimizer-0.9.1.tar.gz diff --git a/python-graphene-django-optimizer.spec b/python-graphene-django-optimizer.spec new file mode 100644 index 0000000..7f2db31 --- /dev/null +++ b/python-graphene-django-optimizer.spec @@ -0,0 +1,711 @@ +%global _empty_manifest_terminate_build 0 +Name: python-graphene-django-optimizer +Version: 0.9.1 +Release: 1 +Summary: Optimize database access inside graphene queries. +License: MIT +URL: https://github.com/tfoxy/graphene-django-optimizer +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/96/00/361d61157e8e3abe70abf0d12c994adbee50acb60a790bddc3c05ce6fb9f/graphene-django-optimizer-0.9.1.tar.gz +BuildArch: noarch + + +%description +# graphene-django-optimizer + +[](https://travis-ci.com/github/tfoxy/graphene-django-optimizer) +[](https://codecov.io/gh/tfoxy/graphene-django-optimizer) +[](https://pypi.org/project/graphene-django-optimizer/) + + + +Optimize queries executed by [graphene-django](https://github.com/graphql-python/graphene-django) automatically, using [`select_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-related), [`prefetch_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#prefetch-related) and [`only`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#only) methods of Django QuerySet. + + + +## Install + +```bash +pip install graphene-django-optimizer +``` + +*Note: If you are using Graphene V2, please install version `0.8`. v0.9 and forward will support only Graphene V3* + +## Usage + +Having the following schema based on [the tutorial of graphene-django](http://docs.graphene-python.org/projects/django/en/latest/tutorial-plain/#hello-graphql-schema-and-object-types) (notice the use of `gql_optimizer`) + +```py +# 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(graphene.ObjectType): + 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: + +```graphql +{ + allIngredients { + id + name + category { + id + name + } + } +} +``` + +```py +# optimized queryset: +ingredients = ( + Ingredient.objects + .select_related('category') + .only('id', 'name', 'category__id', 'category__name') +) +``` + +Fetching all the categories with the related ingredients: + +```graphql +{ + allCategories { + id + name + ingredients { + id + name + } + } +} +``` + +```py +# 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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) +``` + +Notice the usage of the type `OptimizedDjangoObjectType`, which enables +optimization of any single node queries. + +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. + +```py +from django.db.models import Prefetch +import graphene +import graphene_django_optimizer as gql_optimizer + + +class CartType(gql_optimizer.OptimizedDjangoObjectType): + 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. + + +### Optimize with non model fields + +Sometimes we need to have a custom non model fields. In those cases, the optimizer would not optimize with the Django `.only()` method. +So if we still want to optimize with the `.only()` method, we need to use `disable_abort_only` option: + +```py + +class IngredientType(gql_optimizer.OptimizedDjangoObjectType): + calculated_calories = graphene.String() + + class Meta: + model = Ingredient + + def resolve_calculated_calories(root, info): + return get_calories_for_ingredient(root.id) + + +class Query(object): + all_ingredients = graphene.List(IngredientType) + + def resolve_all_ingredients(root, info): + return gql_optimizer.query(Ingredient.objects.all(), info, disable_abort_only=True) +``` + + + + +%package -n python3-graphene-django-optimizer +Summary: Optimize database access inside graphene queries. +Provides: python-graphene-django-optimizer +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-graphene-django-optimizer +# graphene-django-optimizer + +[](https://travis-ci.com/github/tfoxy/graphene-django-optimizer) +[](https://codecov.io/gh/tfoxy/graphene-django-optimizer) +[](https://pypi.org/project/graphene-django-optimizer/) + + + +Optimize queries executed by [graphene-django](https://github.com/graphql-python/graphene-django) automatically, using [`select_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-related), [`prefetch_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#prefetch-related) and [`only`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#only) methods of Django QuerySet. + + + +## Install + +```bash +pip install graphene-django-optimizer +``` + +*Note: If you are using Graphene V2, please install version `0.8`. v0.9 and forward will support only Graphene V3* + +## Usage + +Having the following schema based on [the tutorial of graphene-django](http://docs.graphene-python.org/projects/django/en/latest/tutorial-plain/#hello-graphql-schema-and-object-types) (notice the use of `gql_optimizer`) + +```py +# 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(graphene.ObjectType): + 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: + +```graphql +{ + allIngredients { + id + name + category { + id + name + } + } +} +``` + +```py +# optimized queryset: +ingredients = ( + Ingredient.objects + .select_related('category') + .only('id', 'name', 'category__id', 'category__name') +) +``` + +Fetching all the categories with the related ingredients: + +```graphql +{ + allCategories { + id + name + ingredients { + id + name + } + } +} +``` + +```py +# 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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) +``` + +Notice the usage of the type `OptimizedDjangoObjectType`, which enables +optimization of any single node queries. + +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. + +```py +from django.db.models import Prefetch +import graphene +import graphene_django_optimizer as gql_optimizer + + +class CartType(gql_optimizer.OptimizedDjangoObjectType): + 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. + + +### Optimize with non model fields + +Sometimes we need to have a custom non model fields. In those cases, the optimizer would not optimize with the Django `.only()` method. +So if we still want to optimize with the `.only()` method, we need to use `disable_abort_only` option: + +```py + +class IngredientType(gql_optimizer.OptimizedDjangoObjectType): + calculated_calories = graphene.String() + + class Meta: + model = Ingredient + + def resolve_calculated_calories(root, info): + return get_calories_for_ingredient(root.id) + + +class Query(object): + all_ingredients = graphene.List(IngredientType) + + def resolve_all_ingredients(root, info): + return gql_optimizer.query(Ingredient.objects.all(), info, disable_abort_only=True) +``` + + + + +%package help +Summary: Development documents and examples for graphene-django-optimizer +Provides: python3-graphene-django-optimizer-doc +%description help +# graphene-django-optimizer + +[](https://travis-ci.com/github/tfoxy/graphene-django-optimizer) +[](https://codecov.io/gh/tfoxy/graphene-django-optimizer) +[](https://pypi.org/project/graphene-django-optimizer/) + + + +Optimize queries executed by [graphene-django](https://github.com/graphql-python/graphene-django) automatically, using [`select_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-related), [`prefetch_related`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#prefetch-related) and [`only`](https://docs.djangoproject.com/en/2.0/ref/models/querysets/#only) methods of Django QuerySet. + + + +## Install + +```bash +pip install graphene-django-optimizer +``` + +*Note: If you are using Graphene V2, please install version `0.8`. v0.9 and forward will support only Graphene V3* + +## Usage + +Having the following schema based on [the tutorial of graphene-django](http://docs.graphene-python.org/projects/django/en/latest/tutorial-plain/#hello-graphql-schema-and-object-types) (notice the use of `gql_optimizer`) + +```py +# 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(graphene.ObjectType): + 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: + +```graphql +{ + allIngredients { + id + name + category { + id + name + } + } +} +``` + +```py +# optimized queryset: +ingredients = ( + Ingredient.objects + .select_related('category') + .only('id', 'name', 'category__id', 'category__name') +) +``` + +Fetching all the categories with the related ingredients: + +```graphql +{ + allCategories { + id + name + ingredients { + id + name + } + } +} +``` + +```py +# 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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: + +```py +import graphene +import graphene_django_optimizer as gql_optimizer + + +class ItemType(gql_optimizer.OptimizedDjangoObjectType): + 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) +``` + +Notice the usage of the type `OptimizedDjangoObjectType`, which enables +optimization of any single node queries. + +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. + +```py +from django.db.models import Prefetch +import graphene +import graphene_django_optimizer as gql_optimizer + + +class CartType(gql_optimizer.OptimizedDjangoObjectType): + 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. + + +### Optimize with non model fields + +Sometimes we need to have a custom non model fields. In those cases, the optimizer would not optimize with the Django `.only()` method. +So if we still want to optimize with the `.only()` method, we need to use `disable_abort_only` option: + +```py + +class IngredientType(gql_optimizer.OptimizedDjangoObjectType): + calculated_calories = graphene.String() + + class Meta: + model = Ingredient + + def resolve_calculated_calories(root, info): + return get_calories_for_ingredient(root.id) + + +class Query(object): + all_ingredients = graphene.List(IngredientType) + + def resolve_all_ingredients(root, info): + return gql_optimizer.query(Ingredient.objects.all(), info, disable_abort_only=True) +``` + + + + +%prep +%autosetup -n graphene-django-optimizer-0.9.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-graphene-django-optimizer -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Tue Apr 11 2023 Python_Bot <Python_Bot@openeuler.org> - 0.9.1-1 +- Package Spec generated @@ -0,0 +1 @@ +221b5de22824e20efbc44e473951cf3b graphene-django-optimizer-0.9.1.tar.gz |
