Browse Source

Merge branch 'master' into v3

pull/1086/head
Jonathan Kim 2 years ago
parent
commit
33c6a54414
  1. 2
      .github/workflows/tests.yml
  2. 21
      docs/settings.rst
  3. 10
      graphene_django/compat.py
  4. 8
      graphene_django/converter.py
  5. 4
      graphene_django/settings.py
  6. 19
      graphene_django/static/graphene_django/graphiql.js
  7. 1
      graphene_django/templates/graphene/graphiql.html
  8. 16
      graphene_django/tests/test_converter.py
  9. 26
      graphene_django/tests/test_types.py
  10. 2
      graphene_django/types.py
  11. 2
      graphene_django/views.py
  12. 4
      tox.ini

2
.github/workflows/tests.yml

@ -8,7 +8,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
django: ["2.2", "3.0"]
django: ["2.2", "3.0", "3.1"]
python-version: ["3.6", "3.7", "3.8"]
steps:

21
docs/settings.rst

@ -186,3 +186,24 @@ Default: ``None``
GRAPHENE = {
'SUBSCRIPTION_PATH': "/ws/graphql"
}
``GRAPHIQL_HEADER_EDITOR_ENABLED``
---------------------
GraphiQL starting from version 1.0.0 allows setting custom headers in similar fashion to query variables.
Set to ``False`` if you want to disable GraphiQL headers editor tab for some reason.
This setting is passed to ``headerEditorEnabled`` GraphiQL options, for details refer to GraphiQLDocs_.
.. _GraphiQLDocs: https://github.com/graphql/graphiql/tree/main/packages/graphiql#options
Default: ``True``
.. code:: python
GRAPHENE = {
'GRAPHIQL_HEADER_EDITOR_ENABLED': True,
}

10
graphene_django/compat.py

@ -8,8 +8,14 @@ try:
from django.contrib.postgres.fields import (
ArrayField,
HStoreField,
JSONField,
JSONField as PGJSONField,
RangeField,
)
except ImportError:
ArrayField, HStoreField, JSONField, RangeField = (MissingType,) * 4
ArrayField, HStoreField, PGJSONField, RangeField = (MissingType,) * 4
try:
# JSONField is only available from Django 3.1
from django.db.models import JSONField
except ImportError:
JSONField = MissingType

8
graphene_django/converter.py

@ -26,9 +26,10 @@ from graphene.utils.str_converters import to_camel_case
from graphql import GraphQLError, assert_valid_name
from graphql.pyutils import register_description
from .compat import ArrayField, HStoreField, JSONField, RangeField
from .fields import DjangoConnectionField, DjangoListField
from .compat import ArrayField, HStoreField, JSONField, PGJSONField, RangeField
from .fields import DjangoListField, DjangoConnectionField
from .settings import graphene_settings
from .utils import import_single_dispatch
from .utils.str_converters import to_const
@ -296,8 +297,9 @@ def convert_postgres_array_to_list(field, registry=None):
@convert_django_field.register(HStoreField)
@convert_django_field.register(PGJSONField)
@convert_django_field.register(JSONField)
def convert_postgres_field_to_string(field, registry=None):
def convert_pg_and_json_field_to_string(field, registry=None):
return JSONString(
description=get_django_field_description(field), required=not field.null
)

4
graphene_django/settings.py

@ -40,6 +40,10 @@ DEFAULTS = {
"DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME": None,
# Use a separate path for handling subscriptions.
"SUBSCRIPTION_PATH": None,
# By default GraphiQL headers editor tab is enabled, set to False to hide it
# This sets headerEditorEnabled GraphiQL option, for details go to
# https://github.com/graphql/graphiql/tree/main/packages/graphiql#options
"GRAPHIQL_HEADER_EDITOR_ENABLED": True,
}
if settings.DEBUG:

19
graphene_django/static/graphene_django/graphiql.js

@ -61,13 +61,15 @@
var fetchURL = locationQuery(otherParams);
// Defines a GraphQL fetcher using the fetch API.
function httpClient(graphQLParams) {
var headers = {
Accept: "application/json",
"Content-Type": "application/json",
};
function httpClient(graphQLParams, opts) {
if (typeof opts === 'undefined') {
opts = {};
}
var headers = opts.headers || {};
headers['Accept'] = headers['Accept'] || 'application/json';
headers['Content-Type'] = headers['Content-Type'] || 'application/json';
if (csrftoken) {
headers["X-CSRFToken"] = csrftoken;
headers['X-CSRFToken'] = csrftoken
}
return fetch(fetchURL, {
method: "post",
@ -108,7 +110,7 @@
var activeSubscription = null;
// Define a GraphQL fetcher that can intelligently route queries based on the operation type.
function graphQLFetcher(graphQLParams) {
function graphQLFetcher(graphQLParams, opts) {
var operationType = getOperationType(graphQLParams);
// If we're about to execute a new operation, and we have an active subscription,
@ -126,7 +128,7 @@
},
};
} else {
return httpClient(graphQLParams);
return httpClient(graphQLParams, opts);
}
}
@ -173,6 +175,7 @@
onEditQuery: onEditQuery,
onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName,
headerEditorEnabled: GRAPHENE_SETTINGS.graphiqlHeaderEditorEnabled,
query: parameters.query,
};
if (parameters.variables) {

1
graphene_django/templates/graphene/graphiql.html

@ -45,6 +45,7 @@ add "&raw" to the end of the URL within a browser.
{% if subscription_path %}
subscriptionPath: "{{subscription_path}}",
{% endif %}
graphiqlHeaderEditorEnabled: {{ graphiql_header_editor_enabled|yesno:"true,false" }},
};
</script>
<script src="{% static 'graphene_django/graphiql.js' %}"></script>

16
graphene_django/tests/test_converter.py

@ -11,7 +11,14 @@ from graphene.relay import ConnectionField, Node
from graphene.types.datetime import Date, DateTime, Time
from graphene.types.json import JSONString
from ..compat import ArrayField, HStoreField, JSONField, MissingType, RangeField
from ..compat import (
ArrayField,
HStoreField,
JSONField,
PGJSONField,
MissingType,
RangeField,
)
from ..converter import (
convert_django_field,
convert_django_field_with_choices,
@ -352,8 +359,13 @@ def test_should_postgres_hstore_convert_string():
assert_conversion(HStoreField, JSONString)
@pytest.mark.skipif(JSONField is MissingType, reason="JSONField should exist")
@pytest.mark.skipif(PGJSONField is MissingType, reason="PGJSONField should exist")
def test_should_postgres_json_convert_string():
assert_conversion(PGJSONField, JSONString)
@pytest.mark.skipif(JSONField is MissingType, reason="JSONField should exist")
def test_should_json_convert_string():
assert_conversion(JSONField, JSONString)

26
graphene_django/tests/test_types.py

@ -9,6 +9,7 @@ from graphene import Connection, Field, Interface, ObjectType, Schema, String
from graphene.relay import Node
from .. import registry
from ..filter import DjangoFilterConnectionField
from ..types import DjangoObjectType, DjangoObjectTypeOptions
from .models import Article as ArticleModel
from .models import Reporter as ReporterModel
@ -662,3 +663,28 @@ class TestDjangoObjectType:
}
"""
)
@with_local_registry
def test_django_objecttype_name_connection_propagation():
class Reporter(DjangoObjectType):
class Meta:
model = ReporterModel
name = "CustomReporterName"
filter_fields = ["email"]
interfaces = (Node,)
class Query(ObjectType):
reporter = Node.Field(Reporter)
reporters = DjangoFilterConnectionField(Reporter)
assert Reporter._meta.name == "CustomReporterName"
schema = str(Schema(query=Query))
assert "type CustomReporterName implements Node {" in schema
assert "type CustomReporterNameConnection {" in schema
assert "type CustomReporterNameEdge {" in schema
assert "type Reporter implements Node {" not in schema
assert "type ReporterConnection {" not in schema
assert "type ReporterEdge {" not in schema

2
graphene_django/types.py

@ -246,7 +246,7 @@ class DjangoObjectType(ObjectType):
connection_class = Connection
connection = connection_class.create_type(
"{}Connection".format(cls.__name__), node=cls
"{}Connection".format(options.get("name") or cls.__name__), node=cls
)
if connection is not None:

2
graphene_django/views.py

@ -154,6 +154,8 @@ class GraphQLView(View):
subscriptions_transport_ws_sri=self.subscriptions_transport_ws_sri,
# The SUBSCRIPTION_PATH setting.
subscription_path=self.subscription_path,
# GraphiQL headers tab,
graphiql_header_editor_enabled=graphene_settings.GRAPHIQL_HEADER_EDITOR_ENABLED,
)
if self.batch:

4
tox.ini

@ -1,6 +1,6 @@
[tox]
envlist =
py{36,37,38}-django{22,30,master},
py{36,37,38}-django{22,30,31,master},
black,flake8
[gh-actions]
@ -13,6 +13,7 @@ python =
DJANGO =
2.2: django22
3.0: django30
3.1: django31
master: djangomaster
[testenv]
@ -28,6 +29,7 @@ deps =
django21: Django>=2.1,<2.2
django22: Django>=2.2,<3.0
django30: Django>=3.0a1,<3.1
django31: Django>=3.1,<3.2
djangomaster: https://github.com/django/django/archive/master.zip
commands = {posargs:py.test --cov=graphene_django graphene_django examples}

Loading…
Cancel
Save