Skip to content

Optimize execute_graphql_request #1474

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 66 additions & 32 deletions graphene_django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic import View
from graphql import OperationType, get_operation_ast, parse
from graphql import (
ExecutionResult,
OperationType,
execute,
get_operation_ast,
parse,
validate_schema,
)
from graphql.error import GraphQLError
from graphql.execution import ExecutionResult
from graphql.execution.middleware import MiddlewareManager
from graphql.language import OperationDefinitionNode
from graphql.validation import validate

from graphene import Schema
from graphene_django.constants import MUTATION_ERRORS_FLAG
Expand Down Expand Up @@ -295,56 +303,82 @@ def execute_graphql_request(
return None
raise HttpError(HttpResponseBadRequest("Must provide query string."))

schema_validation_errors = validate_schema(self.schema.graphql_schema)
if schema_validation_errors:
return ExecutionResult(data=None, errors=schema_validation_errors)

try:
document = parse(query)
except Exception as e:
return ExecutionResult(errors=[e])

if request.method.lower() == "get":
operation_ast = get_operation_ast(document, operation_name)
if operation_ast and operation_ast.operation != OperationType.QUERY:
if show_graphiql:
return None
operation_ast = get_operation_ast(document, operation_name)

raise HttpError(
HttpResponseNotAllowed(
["POST"],
"Can only perform a {} operation from a POST request.".format(
operation_ast.operation.value
),
)
if not operation_ast:
ops_count = len(
[
x
for x in document.definitions
if isinstance(x, OperationDefinitionNode)
]
)
if ops_count > 1:
op_error = (
"Must provide operation name if query contains multiple operations."
)
try:
extra_options = {}
if self.execution_context_class:
extra_options["execution_context_class"] = self.execution_context_class
elif operation_name:
op_error = f"Unknown operation named '{operation_name}'."
else:
op_error = "Must provide a valid operation."

return ExecutionResult(errors=[GraphQLError(op_error)])

if (
request.method.lower() == "get"
and operation_ast.operation != OperationType.QUERY
):
if show_graphiql:
return None

raise HttpError(
HttpResponseNotAllowed(
["POST"],
"Can only perform a {} operation from a POST request.".format(
operation_ast.operation.value
),
)
)

execute_args = (self.schema.graphql_schema, document)
validation_errors = validate(*execute_args)

if validation_errors:
return ExecutionResult(data=None, errors=validation_errors)

options = {
"source": query,
try:
execute_options = {
"root_value": self.get_root_value(request),
"context_value": self.get_context(request),
"variable_values": variables,
"operation_name": operation_name,
"context_value": self.get_context(request),
"middleware": self.get_middleware(request),
}
options.update(extra_options)
if self.execution_context_class:
execute_options[
"execution_context_class"
] = self.execution_context_class

operation_ast = get_operation_ast(document, operation_name)
if (
operation_ast
and operation_ast.operation == OperationType.MUTATION
and (
graphene_settings.ATOMIC_MUTATIONS is True
or connection.settings_dict.get("ATOMIC_MUTATIONS", False) is True
)
):
graphene_settings.ATOMIC_MUTATIONS is True
or connection.settings_dict.get("ATOMIC_MUTATIONS", False) is True
) and operation_ast.operation == OperationType.MUTATION:
with transaction.atomic():
result = self.schema.execute(**options)
result = execute(*execute_args, **execute_options)
if getattr(request, MUTATION_ERRORS_FLAG, False) is True:
transaction.set_rollback(True)
return result

return self.schema.execute(**options)
return execute(*execute_args, **execute_options)
except Exception as e:
return ExecutionResult(errors=[e])

Expand Down