diff --git a/graphene_django/views.py b/graphene_django/views.py index c6090b08..9fc61720 100644 --- a/graphene_django/views.py +++ b/graphene_django/views.py @@ -9,10 +9,17 @@ 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.validation import validate from graphene import Schema from graphene_django.constants import MUTATION_ERRORS_FLAG @@ -295,43 +302,56 @@ def execute_graphql_request( return None raise HttpError(HttpResponseBadRequest("Must provide query string.")) + schema = self.schema.graphql_schema + + schema_validation_errors = validate_schema(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 ( + request.method.lower() == "get" + and operation_ast is not None + 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 + ), ) - try: - extra_options = {} - if self.execution_context_class: - extra_options["execution_context_class"] = self.execution_context_class + ) + + validation_errors = validate(schema, document) + + 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 + operation_ast is not None and operation_ast.operation == OperationType.MUTATION and ( graphene_settings.ATOMIC_MUTATIONS is True @@ -339,12 +359,12 @@ def execute_graphql_request( ) ): with transaction.atomic(): - result = self.schema.execute(**options) + result = execute(schema, document, **execute_options) if getattr(request, MUTATION_ERRORS_FLAG, False) is True: transaction.set_rollback(True) return result - return self.schema.execute(**options) + return execute(schema, document, **execute_options) except Exception as e: return ExecutionResult(errors=[e])