mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-04 12:23:13 +03:00
Merge branch 'main' into chore/pre-commit
This commit is contained in:
commit
8fb310a900
|
@ -151,7 +151,7 @@ For example the following ``Model`` and ``DjangoObjectType``:
|
||||||
|
|
||||||
Results in the following GraphQL schema definition:
|
Results in the following GraphQL schema definition:
|
||||||
|
|
||||||
.. code::
|
.. code:: graphql
|
||||||
|
|
||||||
type Pet {
|
type Pet {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -178,7 +178,7 @@ You can disable this automatic conversion by setting
|
||||||
fields = ("id", "kind",)
|
fields = ("id", "kind",)
|
||||||
convert_choices_to_enum = False
|
convert_choices_to_enum = False
|
||||||
|
|
||||||
.. code::
|
.. code:: graphql
|
||||||
|
|
||||||
type Pet {
|
type Pet {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -313,7 +313,7 @@ Additionally, Resolvers will receive **any arguments declared in the field defin
|
||||||
bar=graphene.Int()
|
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.
|
# 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()
|
return Question.objects.filter(foo=foo, bar=bar).first()
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ the core graphene pages for more information on customizing the Relay experience
|
||||||
You can now execute queries like:
|
You can now execute queries like:
|
||||||
|
|
||||||
|
|
||||||
.. code:: python
|
.. code:: graphql
|
||||||
|
|
||||||
{
|
{
|
||||||
questions (first: 2, after: "YXJyYXljb25uZWN0aW9uOjEwNQ==") {
|
questions (first: 2, after: "YXJyYXljb25uZWN0aW9uOjEwNQ==") {
|
||||||
|
@ -440,7 +440,7 @@ You can now execute queries like:
|
||||||
|
|
||||||
Which returns:
|
Which returns:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
|
|
|
@ -207,3 +207,22 @@ Default: ``True``
|
||||||
GRAPHENE = {
|
GRAPHENE = {
|
||||||
'GRAPHIQL_HEADER_EDITOR_ENABLED': True,
|
'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,
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ Now sync your database for the first time:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
|
cd ..
|
||||||
python manage.py migrate
|
python manage.py migrate
|
||||||
|
|
||||||
Let's create a few simple models...
|
Let's create a few simple models...
|
||||||
|
@ -77,6 +78,18 @@ Add ingredients as INSTALLED_APPS:
|
||||||
"cookbook.ingredients",
|
"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:
|
Don't forget to create & run migrations:
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from functools import partial
|
||||||
|
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
|
|
||||||
from graphql_relay.connection.array_connection import (
|
from graphql_relay import (
|
||||||
connection_from_array_slice,
|
connection_from_array_slice,
|
||||||
cursor_to_offset,
|
cursor_to_offset,
|
||||||
get_offset_with_default,
|
get_offset_with_default,
|
||||||
|
|
|
@ -41,6 +41,7 @@ DEFAULTS = {
|
||||||
# This sets headerEditorEnabled GraphiQL option, for details go to
|
# This sets headerEditorEnabled GraphiQL option, for details go to
|
||||||
# https://github.com/graphql/graphiql/tree/main/packages/graphiql#options
|
# https://github.com/graphql/graphiql/tree/main/packages/graphiql#options
|
||||||
"GRAPHIQL_HEADER_EDITOR_ENABLED": True,
|
"GRAPHIQL_HEADER_EDITOR_ENABLED": True,
|
||||||
|
"GRAPHIQL_SHOULD_PERSIST_HEADERS": False,
|
||||||
"ATOMIC_MUTATIONS": False,
|
"ATOMIC_MUTATIONS": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,6 @@
|
||||||
history,
|
history,
|
||||||
location,
|
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
|
// Collect the URL parameters
|
||||||
var parameters = {};
|
var parameters = {};
|
||||||
|
@ -68,9 +60,19 @@
|
||||||
var headers = opts.headers || {};
|
var headers = opts.headers || {};
|
||||||
headers['Accept'] = headers['Accept'] || 'application/json';
|
headers['Accept'] = headers['Accept'] || 'application/json';
|
||||||
headers['Content-Type'] = headers['Content-Type'] || '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) {
|
if (csrftoken) {
|
||||||
headers['X-CSRFToken'] = csrftoken
|
headers['X-CSRFToken'] = csrftoken
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetch(fetchURL, {
|
return fetch(fetchURL, {
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: headers,
|
headers: headers,
|
||||||
|
@ -176,6 +178,7 @@
|
||||||
onEditVariables: onEditVariables,
|
onEditVariables: onEditVariables,
|
||||||
onEditOperationName: onEditOperationName,
|
onEditOperationName: onEditOperationName,
|
||||||
headerEditorEnabled: GRAPHENE_SETTINGS.graphiqlHeaderEditorEnabled,
|
headerEditorEnabled: GRAPHENE_SETTINGS.graphiqlHeaderEditorEnabled,
|
||||||
|
shouldPersistHeaders: GRAPHENE_SETTINGS.graphiqlShouldPersistHeaders,
|
||||||
query: parameters.query,
|
query: parameters.query,
|
||||||
};
|
};
|
||||||
if (parameters.variables) {
|
if (parameters.variables) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ add "&raw" to the end of the URL within a browser.
|
||||||
subscriptionPath: "{{subscription_path}}",
|
subscriptionPath: "{{subscription_path}}",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
graphiqlHeaderEditorEnabled: {{ graphiql_header_editor_enabled|yesno:"true,false" }},
|
graphiqlHeaderEditorEnabled: {{ graphiql_header_editor_enabled|yesno:"true,false" }},
|
||||||
|
graphiqlShouldPersistHeaders: {{ graphiql_should_persist_headers|yesno:"true,false" }},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script src="{% static 'graphene_django/graphiql.js' %}"></script>
|
<script src="{% static 'graphene_django/graphiql.js' %}"></script>
|
||||||
|
|
|
@ -114,7 +114,9 @@ class TestShouldCallGetQuerySetOnForeignKey:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = self.schema.execute(
|
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 not result.errors
|
||||||
assert result.data == {"reporter": {"firstName": "Jane"}}
|
assert result.data == {"reporter": {"firstName": "Jane"}}
|
||||||
|
@ -149,7 +151,9 @@ class TestShouldCallGetQuerySetOnForeignKey:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = self.schema.execute(
|
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 not result.errors
|
||||||
assert result.data["article"] == {
|
assert result.data["article"] == {
|
||||||
|
@ -170,7 +174,9 @@ class TestShouldCallGetQuerySetOnForeignKey:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = self.schema.execute(
|
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 not result.errors
|
||||||
assert result.data["reporter"] == {
|
assert result.data["reporter"] == {
|
||||||
|
|
|
@ -122,7 +122,7 @@ def validate_fields(type_, model, fields, only_fields, exclude_fields):
|
||||||
|
|
||||||
|
|
||||||
class DjangoObjectTypeOptions(ObjectTypeOptions):
|
class DjangoObjectTypeOptions(ObjectTypeOptions):
|
||||||
model = None # type: Model
|
model = None # type: Type[Model]
|
||||||
registry = None # type: Registry
|
registry = None # type: Registry
|
||||||
connection = None # type: Type[Connection]
|
connection = None # type: Type[Connection]
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ class GraphQLView(View):
|
||||||
subscription_path=self.subscription_path,
|
subscription_path=self.subscription_path,
|
||||||
# GraphiQL headers tab,
|
# GraphiQL headers tab,
|
||||||
graphiql_header_editor_enabled=graphene_settings.GRAPHIQL_HEADER_EDITOR_ENABLED,
|
graphiql_header_editor_enabled=graphene_settings.GRAPHIQL_HEADER_EDITOR_ENABLED,
|
||||||
|
graphiql_should_persist_headers=graphene_settings.GRAPHIQL_SHOULD_PERSIST_HEADERS,
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.batch:
|
if self.batch:
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -59,8 +59,7 @@ setup(
|
||||||
keywords="api graphql protocol rest relay graphene",
|
keywords="api graphql protocol rest relay graphene",
|
||||||
packages=find_packages(exclude=["tests", "examples", "examples.*"]),
|
packages=find_packages(exclude=["tests", "examples", "examples.*"]),
|
||||||
install_requires=[
|
install_requires=[
|
||||||
# "graphene>=3.0,<4",
|
"graphene>=3.0,<4",
|
||||||
"graphene @ git+https://github.com/loft-orbital/graphene.git@loft-v3-1.0#egg=graphene",
|
|
||||||
"graphql-core>=3.1.0,<4",
|
"graphql-core>=3.1.0,<4",
|
||||||
"graphql-relay>=3.1.1,<4",
|
"graphql-relay>=3.1.1,<4",
|
||||||
"Django>=3.2",
|
"Django>=3.2",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user