mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-10 16:22:20 +03:00
feat: added bypass_get_queryset decorator
This commit is contained in:
parent
91ddfbd7f2
commit
42d1621e13
|
@ -155,6 +155,11 @@ If you are using ``DjangoObjectType`` you can define a custom `get_queryset`.
|
||||||
to Django documentation about ``prefetch_related``: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#prefetch-related.
|
to Django documentation about ``prefetch_related``: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#prefetch-related.
|
||||||
|
|
||||||
|
|
||||||
|
If you want to explicitly disable the execution of the custom ``get_queryset`` when resolving,
|
||||||
|
you can decorate the resolver with `@graphene_django.bypass_get_queryset`. Note that this
|
||||||
|
can lead to authorization leaks if you are performing authorization checks in the custom
|
||||||
|
``get_queryset``.
|
||||||
|
|
||||||
Filtering ID-based Node Access
|
Filtering ID-based Node Access
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
@ -207,8 +212,8 @@ For Django 2.2 and above:
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# some other urls
|
# some other urls
|
||||||
path('graphql/', PrivateGraphQLView.as_view(graphiql=True, schema=schema)),
|
path('graphql/', PrivateGraphQLView.as_view(graphiql=True, schema=schema)),
|
||||||
]
|
]
|
||||||
|
|
||||||
.. _LoginRequiredMixin: https://docs.djangoproject.com/en/dev/topics/auth/default/#the-loginrequired-mixin
|
.. _LoginRequiredMixin: https://docs.djangoproject.com/en/dev/topics/auth/default/#the-loginrequired-mixin
|
||||||
|
|
|
@ -57,9 +57,9 @@ specify the parameters in your settings.py:
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
GRAPHENE = {
|
GRAPHENE = {
|
||||||
'SCHEMA': 'tutorial.quickstart.schema',
|
'SCHEMA': 'tutorial.quickstart.schema',
|
||||||
'SCHEMA_OUTPUT': 'data/schema.json', # defaults to schema.json,
|
'SCHEMA_OUTPUT': 'data/schema.json', # defaults to schema.json,
|
||||||
'SCHEMA_INDENT': 2, # Defaults to None (displays all data on a single line)
|
'SCHEMA_INDENT': 2, # Defaults to None (displays all data on a single line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from .fields import DjangoConnectionField, DjangoListField
|
from .fields import DjangoConnectionField, DjangoListField
|
||||||
from .types import DjangoObjectType
|
from .types import DjangoObjectType
|
||||||
|
from .utils import bypass_get_queryset
|
||||||
|
|
||||||
__version__ = "3.1.1"
|
__version__ = "3.1.1"
|
||||||
|
|
||||||
|
@ -8,4 +9,5 @@ __all__ = [
|
||||||
"DjangoObjectType",
|
"DjangoObjectType",
|
||||||
"DjangoListField",
|
"DjangoListField",
|
||||||
"DjangoConnectionField",
|
"DjangoConnectionField",
|
||||||
|
"bypass_get_queryset",
|
||||||
]
|
]
|
||||||
|
|
|
@ -278,11 +278,13 @@ def convert_onetoone_field_to_djangomodel(field, registry=None):
|
||||||
"""
|
"""
|
||||||
resolver = super().wrap_resolve(parent_resolver)
|
resolver = super().wrap_resolve(parent_resolver)
|
||||||
|
|
||||||
# If `get_queryset` was not overridden in the DjangoObjectType,
|
# If `get_queryset` was not overridden in the DjangoObjectType
|
||||||
|
# or if we explicitly bypass the `get_queryset` method,
|
||||||
# we can just return the default resolver.
|
# we can just return the default resolver.
|
||||||
if (
|
if (
|
||||||
_type.get_queryset.__func__
|
_type.get_queryset.__func__
|
||||||
is DjangoObjectType.get_queryset.__func__
|
is DjangoObjectType.get_queryset.__func__
|
||||||
|
or getattr(resolver, "_bypass_get_queryset", False)
|
||||||
):
|
):
|
||||||
return resolver
|
return resolver
|
||||||
|
|
||||||
|
@ -379,11 +381,13 @@ def convert_field_to_djangomodel(field, registry=None):
|
||||||
"""
|
"""
|
||||||
resolver = super().wrap_resolve(parent_resolver)
|
resolver = super().wrap_resolve(parent_resolver)
|
||||||
|
|
||||||
# If `get_queryset` was not overridden in the DjangoObjectType,
|
# If `get_queryset` was not overridden in the DjangoObjectType
|
||||||
|
# or if we explicitly bypass the `get_queryset` method,
|
||||||
# we can just return the default resolver.
|
# we can just return the default resolver.
|
||||||
if (
|
if (
|
||||||
_type.get_queryset.__func__
|
_type.get_queryset.__func__
|
||||||
is DjangoObjectType.get_queryset.__func__
|
is DjangoObjectType.get_queryset.__func__
|
||||||
|
or getattr(resolver, "_bypass_get_queryset", False)
|
||||||
):
|
):
|
||||||
return resolver
|
return resolver
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ from .utils import (
|
||||||
get_reverse_fields,
|
get_reverse_fields,
|
||||||
is_valid_django_model,
|
is_valid_django_model,
|
||||||
maybe_queryset,
|
maybe_queryset,
|
||||||
|
bypass_get_queryset,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -16,4 +17,5 @@ __all__ = [
|
||||||
"camelize",
|
"camelize",
|
||||||
"is_valid_django_model",
|
"is_valid_django_model",
|
||||||
"GraphQLTestCase",
|
"GraphQLTestCase",
|
||||||
|
"bypass_get_queryset",
|
||||||
]
|
]
|
||||||
|
|
|
@ -105,3 +105,12 @@ def set_rollback():
|
||||||
atomic_requests = connection.settings_dict.get("ATOMIC_REQUESTS", False)
|
atomic_requests = connection.settings_dict.get("ATOMIC_REQUESTS", False)
|
||||||
if atomic_requests and connection.in_atomic_block:
|
if atomic_requests and connection.in_atomic_block:
|
||||||
transaction.set_rollback(True)
|
transaction.set_rollback(True)
|
||||||
|
|
||||||
|
|
||||||
|
def bypass_get_queryset(resolver):
|
||||||
|
"""
|
||||||
|
Adds a bypass_get_queryset attribute to the resolver, which is used to
|
||||||
|
bypass any custom get_queryset method of the DjangoObjectType.
|
||||||
|
"""
|
||||||
|
resolver._bypass_get_queryset = True
|
||||||
|
return resolver
|
||||||
|
|
Loading…
Reference in New Issue
Block a user