diff --git a/examples/cookbook-plain/requirements.txt b/examples/cookbook-plain/requirements.txt index a693bd1..362a39a 100644 --- a/examples/cookbook-plain/requirements.txt +++ b/examples/cookbook-plain/requirements.txt @@ -1,4 +1,4 @@ graphene graphene-django -graphql-core +graphql-core>=2.1rc1 django==1.9 diff --git a/examples/cookbook/requirements.txt b/examples/cookbook/requirements.txt index 66fa629..6261e04 100644 --- a/examples/cookbook/requirements.txt +++ b/examples/cookbook/requirements.txt @@ -1,5 +1,5 @@ graphene graphene-django -graphql-core +graphql-core>=2.1rc1 django==1.9 django-filter==0.11.0 diff --git a/graphene_django/tests/test_views.py b/graphene_django/tests/test_views.py index fa62063..dd3bfb2 100644 --- a/graphene_django/tests/test_views.py +++ b/graphene_django/tests/test_views.py @@ -448,7 +448,11 @@ def test_handles_field_errors_caught_by_graphql(client): assert response.status_code == 200 assert response_json(response) == { 'data': None, - 'errors': [{'locations': [{'column': 2, 'line': 1}], 'message': 'Throws!'}] + 'errors': [{ + 'locations': [{'column': 2, 'line': 1}], + 'path': ['thrower'], + 'message': 'Throws!', + }] } @@ -457,7 +461,7 @@ def test_handles_syntax_errors_caught_by_graphql(client): assert response.status_code == 400 assert response_json(response) == { 'errors': [{'locations': [{'column': 1, 'line': 1}], - 'message': 'Syntax Error GraphQL request (1:1) ' + 'message': 'Syntax Error GraphQL (1:1) ' 'Unexpected Name "syntaxerror"\n\n1: syntaxerror\n ^\n'}] } diff --git a/graphene_django/views.py b/graphene_django/views.py index a8f203c..fad49db 100644 --- a/graphene_django/views.py +++ b/graphene_django/views.py @@ -10,12 +10,11 @@ from django.utils.decorators import method_decorator from django.views.generic import View from django.views.decorators.csrf import ensure_csrf_cookie -from graphql import Source, execute, parse, validate +from graphql import get_default_backend from graphql.error import format_error as format_graphql_error from graphql.error import GraphQLError from graphql.execution import ExecutionResult from graphql.type.schema import GraphQLSchema -from graphql.utils.get_operation_ast import get_operation_ast from .settings import graphene_settings @@ -59,16 +58,20 @@ class GraphQLView(View): schema = None graphiql = False executor = None + backend = None middleware = None root_value = None pretty = False batch = False def __init__(self, schema=None, executor=None, middleware=None, root_value=None, graphiql=False, pretty=False, - batch=False): + batch=False, backend=None): if not schema: schema = graphene_settings.SCHEMA + if backend is None: + backend = get_default_backend() + if middleware is None: middleware = graphene_settings.MIDDLEWARE @@ -80,6 +83,7 @@ class GraphQLView(View): self.pretty = self.pretty or pretty self.graphiql = self.graphiql or graphiql self.batch = self.batch or batch + self.backend = backend assert isinstance( self.schema, GraphQLSchema), 'A Schema is required to be provided to GraphQLView.' @@ -96,6 +100,9 @@ class GraphQLView(View): def get_context(self, request): return request + def get_backend(self, request): + return self.backend + @method_decorator(ensure_csrf_cookie) def dispatch(self, request, *args, **kwargs): try: @@ -225,9 +232,6 @@ class GraphQLView(View): return {} - def execute(self, *args, **kwargs): - return execute(self.schema, *args, **kwargs) - def execute_graphql_request(self, request, data, query, variables, operation_name, show_graphiql=False): if not query: if show_graphiql: @@ -235,39 +239,37 @@ class GraphQLView(View): raise HttpError(HttpResponseBadRequest( 'Must provide query string.')) - source = Source(query, name='GraphQL request') - try: - document_ast = parse(source) - validation_errors = validate(self.schema, document_ast) - if validation_errors: - return ExecutionResult( - errors=validation_errors, - invalid=True, - ) + backend = self.get_backend(request) + document = backend.document_from_string(self.schema, query) except Exception as e: return ExecutionResult(errors=[e], invalid=True) if request.method.lower() == 'get': - operation_ast = get_operation_ast(document_ast, operation_name) - if operation_ast and operation_ast.operation != 'query': + operation_type = document.get_operation_type(operation_name) + if operation_type and operation_type != 'query': if show_graphiql: return None raise HttpError(HttpResponseNotAllowed( ['POST'], 'Can only perform a {} operation from a POST request.'.format( - operation_ast.operation) + operation_type) )) try: - return self.execute( - document_ast, - root_value=self.get_root_value(request), - variable_values=variables, + extra_options = {} + if self.executor: + # We only include it optionally since + # executor is not a valid argument in all backends + extra_options['executor'] = self.executor + + return document.execute( + root=self.get_root_value(request), + variables=variables, operation_name=operation_name, - context_value=self.get_context(request), + context=self.get_context(request), middleware=self.get_middleware(request), - executor=self.executor, + **extra_options ) except Exception as e: return ExecutionResult(errors=[e], invalid=True) diff --git a/setup.py b/setup.py index 5e058b4..97d34e1 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,7 @@ setup( install_requires=[ 'six>=1.10.0', 'graphene>=2.0.1,<3', + 'graphql-core>=2.1rc1', django_version, 'iso8601', 'singledispatch>=3.4.0.3',