From 541caa117eedf74923c2ed396afeee5fd568850e Mon Sep 17 00:00:00 2001 From: Firas K <3097061+firaskafri@users.noreply.github.com> Date: Sat, 24 Sep 2022 15:50:40 +0300 Subject: [PATCH 1/8] Fixes related to pr#1412 (#1352) * fix: setup.py graphene dependency * fix: graphene_django/tests/test_get_queryset.py format Co-authored-by: Firas Kafri --- graphene_django/tests/test_get_queryset.py | 12 +++++++++--- setup.py | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/graphene_django/tests/test_get_queryset.py b/graphene_django/tests/test_get_queryset.py index b2647c3..91bdc70 100644 --- a/graphene_django/tests/test_get_queryset.py +++ b/graphene_django/tests/test_get_queryset.py @@ -114,7 +114,9 @@ class TestShouldCallGetQuerySetOnForeignKey: """ result = self.schema.execute( - query, variables={"id": self.reporter.id}, context_value={"admin": True}, + query, + variables={"id": self.reporter.id}, + context_value={"admin": True}, ) assert not result.errors assert result.data == {"reporter": {"firstName": "Jane"}} @@ -149,7 +151,9 @@ class TestShouldCallGetQuerySetOnForeignKey: """ result = self.schema.execute( - query, variables={"id": self.articles[0].id}, context_value={"admin": True}, + query, + variables={"id": self.articles[0].id}, + context_value={"admin": True}, ) assert not result.errors assert result.data["article"] == { @@ -170,7 +174,9 @@ class TestShouldCallGetQuerySetOnForeignKey: """ result = self.schema.execute( - query, variables={"id": self.reporter.id}, context_value={"admin": True}, + query, + variables={"id": self.reporter.id}, + context_value={"admin": True}, ) assert not result.errors assert result.data["reporter"] == { diff --git a/setup.py b/setup.py index 3a46d24..d9aefef 100644 --- a/setup.py +++ b/setup.py @@ -59,8 +59,7 @@ setup( keywords="api graphql protocol rest relay graphene", packages=find_packages(exclude=["tests", "examples", "examples.*"]), install_requires=[ - # "graphene>=3.0,<4", - "graphene @ git+https://github.com/loft-orbital/graphene.git@loft-v3-1.0#egg=graphene", + "graphene>=3.0,<4", "graphql-core>=3.1.0,<4", "graphql-relay>=3.1.1,<4", "Django>=3.2", From 05d3df92e7be6e1c547f2cb1b3b55ff13339f713 Mon Sep 17 00:00:00 2001 From: Craig <41215134+c-py@users.noreply.github.com> Date: Sat, 24 Sep 2022 22:59:53 +1000 Subject: [PATCH 2/8] Delay assignment of csrftoken (#1289) --- .../static/graphene_django/graphiql.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/graphene_django/static/graphene_django/graphiql.js b/graphene_django/static/graphene_django/graphiql.js index ac010e8..f457f65 100644 --- a/graphene_django/static/graphene_django/graphiql.js +++ b/graphene_django/static/graphene_django/graphiql.js @@ -10,14 +10,6 @@ history, location, ) { - // Parse the cookie value for a CSRF token - var csrftoken; - var cookies = ("; " + document.cookie).split("; csrftoken="); - if (cookies.length == 2) { - csrftoken = cookies.pop().split(";").shift(); - } else { - csrftoken = document.querySelector("[name=csrfmiddlewaretoken]").value; - } // Collect the URL parameters var parameters = {}; @@ -68,9 +60,19 @@ var headers = opts.headers || {}; headers['Accept'] = headers['Accept'] || 'application/json'; headers['Content-Type'] = headers['Content-Type'] || 'application/json'; + + // Parse the cookie value for a CSRF token + var csrftoken; + var cookies = ("; " + document.cookie).split("; csrftoken="); + if (cookies.length == 2) { + csrftoken = cookies.pop().split(";").shift(); + } else { + csrftoken = document.querySelector("[name=csrfmiddlewaretoken]").value; + } if (csrftoken) { headers['X-CSRFToken'] = csrftoken } + return fetch(fetchURL, { method: "post", headers: headers, From 60b30320146313f25d072394252990f2e8115cde Mon Sep 17 00:00:00 2001 From: belkka Date: Sat, 24 Sep 2022 16:00:12 +0300 Subject: [PATCH 3/8] Fix type hint for DjangoObjectTypeOptions.model (#1269) Proper type is `typing.Type[Model]`, not `Model` --- graphene_django/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene_django/types.py b/graphene_django/types.py index c256f1d..0ebb7d3 100644 --- a/graphene_django/types.py +++ b/graphene_django/types.py @@ -122,7 +122,7 @@ def validate_fields(type_, model, fields, only_fields, exclude_fields): class DjangoObjectTypeOptions(ObjectTypeOptions): - model = None # type: Model + model = None # type: Type[Model] registry = None # type: Registry connection = None # type: Type[Connection] From 97442f9ceeb1061d24e022bd7044a63d4230d53b Mon Sep 17 00:00:00 2001 From: belkka Date: Sat, 24 Sep 2022 16:00:22 +0300 Subject: [PATCH 4/8] Fix code examples in queries.rst (#1265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix code examples in queries.rst Code example in Arguments section doesn't work as stated in its comment — if "foo" or "bar" are not declare in the graphql query, it will be an error, not they become None. Code example in Info section has invalid indentation, `resolve_questions()` seems to be a `Query` method, but it's indented as module-level function. * Fix indentation in query examples * Enable syntax highlight for graphql queries --- docs/queries.rst | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/queries.rst b/docs/queries.rst index 1e1ba82..8b85d45 100644 --- a/docs/queries.rst +++ b/docs/queries.rst @@ -151,7 +151,7 @@ For example the following ``Model`` and ``DjangoObjectType``: Results in the following GraphQL schema definition: -.. code:: +.. code:: graphql type Pet { id: ID! @@ -178,7 +178,7 @@ You can disable this automatic conversion by setting fields = ("id", "kind",) convert_choices_to_enum = False -.. code:: +.. code:: graphql type Pet { id: ID! @@ -313,7 +313,7 @@ Additionally, Resolvers will receive **any arguments declared in the field defin bar=graphene.Int() ) - def resolve_question(root, info, foo, bar): + def resolve_question(root, info, foo=None, bar=None): # If `foo` or `bar` are declared in the GraphQL query they will be here, else None. return Question.objects.filter(foo=foo, bar=bar).first() @@ -336,12 +336,12 @@ of Django's ``HTTPRequest`` in your resolve methods, such as checking for authen class Query(graphene.ObjectType): questions = graphene.List(QuestionType) - def resolve_questions(root, info): - # See if a user is authenticated - if info.context.user.is_authenticated(): - return Question.objects.all() - else: - return Question.objects.none() + def resolve_questions(root, info): + # See if a user is authenticated + if info.context.user.is_authenticated(): + return Question.objects.all() + else: + return Question.objects.none() DjangoObjectTypes @@ -418,29 +418,29 @@ the core graphene pages for more information on customizing the Relay experience You can now execute queries like: -.. code:: python +.. code:: graphql { questions (first: 2, after: "YXJyYXljb25uZWN0aW9uOjEwNQ==") { pageInfo { - startCursor - endCursor - hasNextPage - hasPreviousPage + startCursor + endCursor + hasNextPage + hasPreviousPage } edges { - cursor - node { - id - question_text - } + cursor + node { + id + question_text + } } } } Which returns: -.. code:: python +.. code:: json { "data": { From 0b2cc4ecb2c8ad4a12c21ab1384d2ce0c89295cb Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Sat, 24 Sep 2022 09:00:45 -0400 Subject: [PATCH 5/8] Fixed deprecation warning (#1313) --- graphene_django/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene_django/fields.py b/graphene_django/fields.py index 3c48595..05a7010 100644 --- a/graphene_django/fields.py +++ b/graphene_django/fields.py @@ -2,7 +2,7 @@ from functools import partial from django.db.models.query import QuerySet -from graphql_relay.connection.array_connection import ( +from graphql_relay import ( connection_from_array_slice, cursor_to_offset, get_offset_with_default, From 9a60589732411b1b11a190114bc2a412c02d5fe2 Mon Sep 17 00:00:00 2001 From: Gabriel Lacroix Date: Sat, 24 Sep 2022 09:02:33 -0400 Subject: [PATCH 6/8] Make instructions runnable without tweaking (#1224) Introduces two changes to make sure the instructions in the tutorial don't require debugging: - Add `cd ..` when first syncing the database so that `manage.py` is accessible in the working directory. - Change `cookbook.ingredients.apps.IngredientsConfig.name` to `cookbook.ingredients` from `ingredients` to prevent the following exception: ```python django.core.exceptions.ImproperlyConfigured: Cannot import 'ingredients'. Check that 'cookbook.ingredients.apps.IngredientsConfig.name' is correct. ``` --- docs/tutorial-plain.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/tutorial-plain.rst b/docs/tutorial-plain.rst index 45927a5..43b6da9 100644 --- a/docs/tutorial-plain.rst +++ b/docs/tutorial-plain.rst @@ -35,6 +35,7 @@ Now sync your database for the first time: .. code:: bash + cd .. python manage.py migrate Let's create a few simple models... @@ -77,6 +78,18 @@ Add ingredients as INSTALLED_APPS: "cookbook.ingredients", ] +Make sure the app name in ``cookbook.ingredients.apps.IngredientsConfig`` is set to ``cookbook.ingredients``. + +.. code:: python + + # cookbook/ingredients/apps.py + + from django.apps import AppConfig + + + class IngredientsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'cookbook.ingredients' Don't forget to create & run migrations: From 07940aa5f537bb5e38af3bd38bc1b770bf678cd1 Mon Sep 17 00:00:00 2001 From: Alan Rivas Date: Sat, 24 Sep 2022 10:03:45 -0300 Subject: [PATCH 7/8] Update tutorial-relay.rst (#1220) From a78114ada346fb2c639ea88fe81d0407cf5ed448 Mon Sep 17 00:00:00 2001 From: Suyeol Jeon Date: Sat, 24 Sep 2022 23:41:14 +0900 Subject: [PATCH 8/8] Add support to persist GraphQL headers in GraphiQL (#1209) --- docs/settings.rst | 19 +++++++++++++++++++ graphene_django/settings.py | 1 + .../static/graphene_django/graphiql.js | 1 + .../templates/graphene/graphiql.html | 1 + graphene_django/views.py | 1 + 5 files changed, 23 insertions(+) diff --git a/docs/settings.rst b/docs/settings.rst index ff1c05e..1984a15 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -207,3 +207,22 @@ Default: ``True`` GRAPHENE = { 'GRAPHIQL_HEADER_EDITOR_ENABLED': True, } + + +``GRAPHIQL_SHOULD_PERSIST_HEADERS`` +--------------------- + +Set to ``True`` if you want to persist GraphiQL headers after refreshing the page. + +This setting is passed to ``shouldPersistHeaders`` GraphiQL options, for details refer to GraphiQLDocs_. + +.. _GraphiQLDocs: https://github.com/graphql/graphiql/tree/main/packages/graphiql#options + + +Default: ``False`` + +.. code:: python + + GRAPHENE = { + 'GRAPHIQL_SHOULD_PERSIST_HEADERS': False, + } diff --git a/graphene_django/settings.py b/graphene_django/settings.py index 467c6a3..0fd70a7 100644 --- a/graphene_django/settings.py +++ b/graphene_django/settings.py @@ -41,6 +41,7 @@ DEFAULTS = { # This sets headerEditorEnabled GraphiQL option, for details go to # https://github.com/graphql/graphiql/tree/main/packages/graphiql#options "GRAPHIQL_HEADER_EDITOR_ENABLED": True, + "GRAPHIQL_SHOULD_PERSIST_HEADERS": False, "ATOMIC_MUTATIONS": False, } diff --git a/graphene_django/static/graphene_django/graphiql.js b/graphene_django/static/graphene_django/graphiql.js index f457f65..f6be32c 100644 --- a/graphene_django/static/graphene_django/graphiql.js +++ b/graphene_django/static/graphene_django/graphiql.js @@ -178,6 +178,7 @@ onEditVariables: onEditVariables, onEditOperationName: onEditOperationName, headerEditorEnabled: GRAPHENE_SETTINGS.graphiqlHeaderEditorEnabled, + shouldPersistHeaders: GRAPHENE_SETTINGS.graphiqlShouldPersistHeaders, query: parameters.query, }; if (parameters.variables) { diff --git a/graphene_django/templates/graphene/graphiql.html b/graphene_django/templates/graphene/graphiql.html index cec4893..3685692 100644 --- a/graphene_django/templates/graphene/graphiql.html +++ b/graphene_django/templates/graphene/graphiql.html @@ -46,6 +46,7 @@ add "&raw" to the end of the URL within a browser. subscriptionPath: "{{subscription_path}}", {% endif %} graphiqlHeaderEditorEnabled: {{ graphiql_header_editor_enabled|yesno:"true,false" }}, + graphiqlShouldPersistHeaders: {{ graphiql_should_persist_headers|yesno:"true,false" }}, }; diff --git a/graphene_django/views.py b/graphene_django/views.py index f533f70..bf333a9 100644 --- a/graphene_django/views.py +++ b/graphene_django/views.py @@ -162,6 +162,7 @@ class GraphQLView(View): subscription_path=self.subscription_path, # GraphiQL headers tab, graphiql_header_editor_enabled=graphene_settings.GRAPHIQL_HEADER_EDITOR_ENABLED, + graphiql_should_persist_headers=graphene_settings.GRAPHIQL_SHOULD_PERSIST_HEADERS, ) if self.batch: