From 5a1e014b9a0a388acec53a6a67687de56faec205 Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 13 Nov 2015 16:53:35 -0500 Subject: [PATCH 1/4] Use `graphql-django-view` to handle `GraphQLView` --- graphene/contrib/django/views.py | 73 ++++-------------------------- setup.py | 3 +- tests/contrib_django/test_urls.py | 3 +- tests/contrib_django/test_views.py | 2 +- tox.ini | 3 +- 5 files changed, 15 insertions(+), 69 deletions(-) diff --git a/graphene/contrib/django/views.py b/graphene/contrib/django/views.py index cb415df6..30502d03 100644 --- a/graphene/contrib/django/views.py +++ b/graphene/contrib/django/views.py @@ -1,67 +1,10 @@ -import json - -from django.conf import settings -from django.http import HttpResponse -from django.views.generic import View - -from graphql.core.error import GraphQLError, format_error +from graphql_django_view import GraphQLView as BaseGraphQLView -def form_error(error): - if isinstance(error, GraphQLError): - return format_error(error) - return error - - -class GraphQLView(View): - schema = None - - @staticmethod - def format_result(result): - data = {'data': result.data} - if result.errors: - data['errors'] = list(map(form_error, result.errors)) - - return data - - def response_errors(self, *errors): - errors = [{ - "message": str(e) - } for e in errors] - return HttpResponse(json.dumps({'errors': errors}), content_type='application/json') - - def execute_query(self, request, query, *args, **kwargs): - if not query: - return self.response_errors(Exception("Must provide query string.")) - else: - try: - result = self.schema.execute(query, *args, **kwargs) - data = self.format_result(result) - except Exception as e: - if settings.DEBUG: - raise e - return self.response_errors(e) - return HttpResponse(json.dumps(data), content_type='application/json') - - def get(self, request, *args, **kwargs): - query = request.GET.get('query') - return self.execute_query(request, query or '') - - @staticmethod - def get_content_type(request): - meta = request.META - return meta.get('CONTENT_TYPE', meta.get('HTTP_CONTENT_TYPE', '')) - - def post(self, request, *args, **kwargs): - content_type = self.get_content_type(request) - if content_type == 'application/json': - try: - received_json_data = json.loads(request.body.decode()) - query = received_json_data.get('query') - except ValueError: - return self.response_errors(ValueError("Malformed json body in the post data")) - elif content_type == 'application/graphql': - query = request.body.decode() - else: - query = request.POST.get('query') or request.GET.get('query') - return self.execute_query(request, query or '') +class GraphQLView(BaseGraphQLView): + def __init__(self, schema, **kwargs): + super(GraphQLView, self).__init__( + schema=schema.schema, + executor=schema.executor, + **kwargs + ) diff --git a/setup.py b/setup.py index c3ab220b..d44372cb 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,8 @@ setup( install_requires=[ 'six>=1.10.0', 'blinker', - 'graphql-core==0.4.7b0', + 'graphql-core==0.4.7b2', + 'graphql-django-view>=1.0.0', 'graphql-relay==0.3.3' ], tests_require=[ diff --git a/tests/contrib_django/test_urls.py b/tests/contrib_django/test_urls.py index 2f0801ee..17fd391c 100644 --- a/tests/contrib_django/test_urls.py +++ b/tests/contrib_django/test_urls.py @@ -23,7 +23,8 @@ class Human(DjangoNode): class Meta: model = Article - def resolve_raises(self, *args): + @staticmethod + def resolve_raises(*args): raise Exception("This field should raise exception") def get_node(self, id): diff --git a/tests/contrib_django/test_views.py b/tests/contrib_django/test_views.py index 87af180f..b58efb21 100644 --- a/tests/contrib_django/test_views.py +++ b/tests/contrib_django/test_views.py @@ -26,7 +26,7 @@ def test_client_post_malformed_json(settings, client): response = client.post('/graphql', 'MALFORMED', 'application/json') json_response = format_response(response) assert json_response == {'errors': [ - {'message': 'Malformed json body in the post data'}]} + {'message': 'POST body sent invalid JSON.'}]} def test_client_post_empty_query_json(settings, client): diff --git a/tox.ini b/tox.ini index e439ab84..81aa60fa 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,8 @@ deps= pytest>=2.7.2 django>=1.8.0,<1.9 pytest-django - graphql-core==0.4.7b0 + graphql-django-view>=1.0.0 + graphql-core==0.4.7b2 graphql-relay==0.3.3 six blinker From 49a7b15a47114603dfaf9f3eb4c263a999bf7b0d Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 13 Nov 2015 16:55:00 -0500 Subject: [PATCH 2/4] move `graphql-django-view` to djanog extras. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d44372cb..8d626215 100644 --- a/setup.py +++ b/setup.py @@ -57,7 +57,6 @@ setup( 'six>=1.10.0', 'blinker', 'graphql-core==0.4.7b2', - 'graphql-django-view>=1.0.0', 'graphql-relay==0.3.3' ], tests_require=[ @@ -68,6 +67,7 @@ setup( 'django': [ 'Django>=1.6.0,<1.9', 'singledispatch>=3.4.0.3', + 'graphql-django-view>=1.0.0', ], }, From 77a588a5b16851e16106f1de283bf79071854340 Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 13 Nov 2015 17:00:04 -0500 Subject: [PATCH 3/4] Fix handling of root value to be like `Schema.execute`. --- graphene/contrib/django/views.py | 6 ++++++ tests/contrib_django/test_urls.py | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/graphene/contrib/django/views.py b/graphene/contrib/django/views.py index 30502d03..ad245d72 100644 --- a/graphene/contrib/django/views.py +++ b/graphene/contrib/django/views.py @@ -2,9 +2,15 @@ from graphql_django_view import GraphQLView as BaseGraphQLView class GraphQLView(BaseGraphQLView): + graphene_schema = None + def __init__(self, schema, **kwargs): super(GraphQLView, self).__init__( + graphene_schema=schema, schema=schema.schema, executor=schema.executor, **kwargs ) + + def get_root_value(self, request): + return self.graphene_schema.query(super(GraphQLView, self).get_root_value(request)) diff --git a/tests/contrib_django/test_urls.py b/tests/contrib_django/test_urls.py index 17fd391c..2f0801ee 100644 --- a/tests/contrib_django/test_urls.py +++ b/tests/contrib_django/test_urls.py @@ -23,8 +23,7 @@ class Human(DjangoNode): class Meta: model = Article - @staticmethod - def resolve_raises(*args): + def resolve_raises(self, *args): raise Exception("This field should raise exception") def get_node(self, id): From 57ba5e71f97090170527029afedede1abd2e49b1 Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 13 Nov 2015 17:15:42 -0500 Subject: [PATCH 4/4] Remove redundant tests & fix tox. --- graphene/contrib/django/tests/test_views.py | 72 +-------------------- tox.ini | 3 +- 2 files changed, 3 insertions(+), 72 deletions(-) diff --git a/graphene/contrib/django/tests/test_views.py b/graphene/contrib/django/tests/test_views.py index 28fec258..f82be99f 100644 --- a/graphene/contrib/django/tests/test_views.py +++ b/graphene/contrib/django/tests/test_views.py @@ -5,68 +5,6 @@ def format_response(response): return json.loads(response.content.decode()) -def test_client_get_no_query(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.get('/graphql') - json_response = format_response(response) - assert json_response == {'errors': [ - {'message': 'Must provide query string.'}]} - - -def test_client_post_no_query(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post('/graphql', {}) - json_response = format_response(response) - assert json_response == {'errors': [ - {'message': 'Must provide query string.'}]} - - -def test_client_post_malformed_json(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post('/graphql', 'MALFORMED', 'application/json') - json_response = format_response(response) - assert json_response == {'errors': [ - {'message': 'POST body sent invalid JSON.'}]} - - -def test_client_post_empty_query_json(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post( - '/graphql', json.dumps({'query': ''}), 'application/json') - json_response = format_response(response) - assert json_response == {'errors': [ - {'message': 'Must provide query string.'}]} - - -def test_client_post_empty_query_graphql(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post( - '/graphql', '', 'application/graphql') - json_response = format_response(response) - assert json_response == {'errors': [ - {'message': 'Must provide query string.'}]} - - -def test_client_post_bad_query_json(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post( - '/graphql', json.dumps({'query': '{ MALFORMED'}), 'application/json') - json_response = format_response(response) - assert 'errors' in json_response - assert len(json_response['errors']) == 1 - assert 'Syntax Error GraphQL' in json_response['errors'][0]['message'] - - -def test_client_post_bad_query_graphql(settings, client): - settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' - response = client.post( - '/graphql', '{ MALFORMED', 'application/graphql') - json_response = format_response(response) - assert 'errors' in json_response - assert len(json_response['errors']) == 1 - assert 'Syntax Error GraphQL' in json_response['errors'][0]['message'] - - def test_client_get_good_query(settings, client): settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' response = client.get('/graphql', {'query': '{ headline }'}) @@ -83,8 +21,7 @@ def test_client_get_good_query_with_raise(settings, client): settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' response = client.get('/graphql', {'query': '{ raises }'}) json_response = format_response(response) - assert json_response['errors'][0][ - 'message'] == 'This field should raise exception' + assert json_response['errors'][0]['message'] == 'This field should raise exception' assert json_response['data']['raises'] is None @@ -112,10 +49,3 @@ def test_client_post_good_query_graphql(settings, client): } } assert json_response == expected_json - - -# def test_client_get_bad_query(settings, client): -# settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls' -# response = client.get('/graphql') -# json_response = format_response(response) -# assert json_response == {'errors': [{'message': 'Must provide query string.'}]} diff --git a/tox.ini b/tox.ini index 81aa60fa..45cf7fdd 100644 --- a/tox.ini +++ b/tox.ini @@ -13,10 +13,11 @@ deps= six blinker singledispatch + mock setenv = PYTHONPATH = .:{envdir} commands= - py.test tests/ examples/ + py.test [testenv:flake8] deps = flake8