mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-02-18 04:20:34 +03:00
DjangoConnectionField slice: use max_limit first, if set (#965)
This commit is contained in:
parent
40e9c66db3
commit
c00203499b
|
@ -1,4 +1,5 @@
|
||||||
import graphene
|
import graphene
|
||||||
|
import pytest
|
||||||
from graphene.relay import Node
|
from graphene.relay import Node
|
||||||
from graphene_django import DjangoConnectionField, DjangoObjectType
|
from graphene_django import DjangoConnectionField, DjangoObjectType
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ def test_should_query_field():
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(graphene.ObjectType):
|
||||||
reporter = graphene.Field(ReporterType)
|
reporter = graphene.Field(ReporterType)
|
||||||
debug = graphene.Field(DjangoDebug, name="_debug")
|
debug = graphene.Field(DjangoDebug, name="__debug")
|
||||||
|
|
||||||
def resolve_reporter(self, info, **args):
|
def resolve_reporter(self, info, **args):
|
||||||
return Reporter.objects.first()
|
return Reporter.objects.first()
|
||||||
|
@ -34,7 +35,7 @@ def test_should_query_field():
|
||||||
reporter {
|
reporter {
|
||||||
lastName
|
lastName
|
||||||
}
|
}
|
||||||
_debug {
|
__debug {
|
||||||
sql {
|
sql {
|
||||||
rawSql
|
rawSql
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,9 @@ def test_should_query_field():
|
||||||
"""
|
"""
|
||||||
expected = {
|
expected = {
|
||||||
"reporter": {"lastName": "ABA"},
|
"reporter": {"lastName": "ABA"},
|
||||||
"_debug": {"sql": [{"rawSql": str(Reporter.objects.order_by("pk")[:1].query)}]},
|
"__debug": {
|
||||||
|
"sql": [{"rawSql": str(Reporter.objects.order_by("pk")[:1].query)}]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
schema = graphene.Schema(query=Query)
|
schema = graphene.Schema(query=Query)
|
||||||
result = schema.execute(
|
result = schema.execute(
|
||||||
|
@ -53,7 +56,10 @@ def test_should_query_field():
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
def test_should_query_nested_field():
|
@pytest.mark.parametrize("max_limit,does_count", [(None, True), (100, False)])
|
||||||
|
def test_should_query_nested_field(graphene_settings, max_limit, does_count):
|
||||||
|
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = max_limit
|
||||||
|
|
||||||
r1 = Reporter(last_name="ABA")
|
r1 = Reporter(last_name="ABA")
|
||||||
r1.save()
|
r1.save()
|
||||||
r2 = Reporter(last_name="Griffin")
|
r2 = Reporter(last_name="Griffin")
|
||||||
|
@ -111,11 +117,18 @@ def test_should_query_nested_field():
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
query = str(Reporter.objects.order_by("pk")[:1].query)
|
query = str(Reporter.objects.order_by("pk")[:1].query)
|
||||||
assert result.data["__debug"]["sql"][0]["rawSql"] == query
|
assert result.data["__debug"]["sql"][0]["rawSql"] == query
|
||||||
|
if does_count:
|
||||||
assert "COUNT" in result.data["__debug"]["sql"][1]["rawSql"]
|
assert "COUNT" in result.data["__debug"]["sql"][1]["rawSql"]
|
||||||
assert "tests_reporter_pets" in result.data["__debug"]["sql"][2]["rawSql"]
|
assert "tests_reporter_pets" in result.data["__debug"]["sql"][2]["rawSql"]
|
||||||
assert "COUNT" in result.data["__debug"]["sql"][3]["rawSql"]
|
assert "COUNT" in result.data["__debug"]["sql"][3]["rawSql"]
|
||||||
assert "tests_reporter_pets" in result.data["__debug"]["sql"][4]["rawSql"]
|
assert "tests_reporter_pets" in result.data["__debug"]["sql"][4]["rawSql"]
|
||||||
assert len(result.data["__debug"]["sql"]) == 5
|
assert len(result.data["__debug"]["sql"]) == 5
|
||||||
|
else:
|
||||||
|
assert len(result.data["__debug"]["sql"]) == 3
|
||||||
|
for i in range(len(result.data["__debug"]["sql"])):
|
||||||
|
assert "COUNT" not in result.data["__debug"]["sql"][i]["rawSql"]
|
||||||
|
assert "tests_reporter_pets" in result.data["__debug"]["sql"][1]["rawSql"]
|
||||||
|
assert "tests_reporter_pets" in result.data["__debug"]["sql"][2]["rawSql"]
|
||||||
|
|
||||||
assert result.data["reporter"] == expected["reporter"]
|
assert result.data["reporter"] == expected["reporter"]
|
||||||
|
|
||||||
|
@ -133,7 +146,7 @@ def test_should_query_list():
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(graphene.ObjectType):
|
||||||
all_reporters = graphene.List(ReporterType)
|
all_reporters = graphene.List(ReporterType)
|
||||||
debug = graphene.Field(DjangoDebug, name="_debug")
|
debug = graphene.Field(DjangoDebug, name="__debug")
|
||||||
|
|
||||||
def resolve_all_reporters(self, info, **args):
|
def resolve_all_reporters(self, info, **args):
|
||||||
return Reporter.objects.all()
|
return Reporter.objects.all()
|
||||||
|
@ -143,7 +156,7 @@ def test_should_query_list():
|
||||||
allReporters {
|
allReporters {
|
||||||
lastName
|
lastName
|
||||||
}
|
}
|
||||||
_debug {
|
__debug {
|
||||||
sql {
|
sql {
|
||||||
rawSql
|
rawSql
|
||||||
}
|
}
|
||||||
|
@ -152,7 +165,7 @@ def test_should_query_list():
|
||||||
"""
|
"""
|
||||||
expected = {
|
expected = {
|
||||||
"allReporters": [{"lastName": "ABA"}, {"lastName": "Griffin"}],
|
"allReporters": [{"lastName": "ABA"}, {"lastName": "Griffin"}],
|
||||||
"_debug": {"sql": [{"rawSql": str(Reporter.objects.all().query)}]},
|
"__debug": {"sql": [{"rawSql": str(Reporter.objects.all().query)}]},
|
||||||
}
|
}
|
||||||
schema = graphene.Schema(query=Query)
|
schema = graphene.Schema(query=Query)
|
||||||
result = schema.execute(
|
result = schema.execute(
|
||||||
|
@ -162,7 +175,10 @@ def test_should_query_list():
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
def test_should_query_connection():
|
@pytest.mark.parametrize("max_limit,does_count", [(None, True), (100, False)])
|
||||||
|
def test_should_query_connection(graphene_settings, max_limit, does_count):
|
||||||
|
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = max_limit
|
||||||
|
|
||||||
r1 = Reporter(last_name="ABA")
|
r1 = Reporter(last_name="ABA")
|
||||||
r1.save()
|
r1.save()
|
||||||
r2 = Reporter(last_name="Griffin")
|
r2 = Reporter(last_name="Griffin")
|
||||||
|
@ -175,7 +191,7 @@ def test_should_query_connection():
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(graphene.ObjectType):
|
||||||
all_reporters = DjangoConnectionField(ReporterType)
|
all_reporters = DjangoConnectionField(ReporterType)
|
||||||
debug = graphene.Field(DjangoDebug, name="_debug")
|
debug = graphene.Field(DjangoDebug, name="__debug")
|
||||||
|
|
||||||
def resolve_all_reporters(self, info, **args):
|
def resolve_all_reporters(self, info, **args):
|
||||||
return Reporter.objects.all()
|
return Reporter.objects.all()
|
||||||
|
@ -189,7 +205,7 @@ def test_should_query_connection():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_debug {
|
__debug {
|
||||||
sql {
|
sql {
|
||||||
rawSql
|
rawSql
|
||||||
}
|
}
|
||||||
|
@ -203,12 +219,22 @@ def test_should_query_connection():
|
||||||
)
|
)
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
assert result.data["allReporters"] == expected["allReporters"]
|
assert result.data["allReporters"] == expected["allReporters"]
|
||||||
assert "COUNT" in result.data["_debug"]["sql"][0]["rawSql"]
|
if does_count:
|
||||||
|
assert len(result.data["__debug"]["sql"]) == 2
|
||||||
|
assert "COUNT" in result.data["__debug"]["sql"][0]["rawSql"]
|
||||||
query = str(Reporter.objects.all()[:1].query)
|
query = str(Reporter.objects.all()[:1].query)
|
||||||
assert result.data["_debug"]["sql"][1]["rawSql"] == query
|
assert result.data["__debug"]["sql"][1]["rawSql"] == query
|
||||||
|
else:
|
||||||
|
assert len(result.data["__debug"]["sql"]) == 1
|
||||||
|
assert "COUNT" not in result.data["__debug"]["sql"][0]["rawSql"]
|
||||||
|
query = str(Reporter.objects.all()[:1].query)
|
||||||
|
assert result.data["__debug"]["sql"][0]["rawSql"] == query
|
||||||
|
|
||||||
|
|
||||||
def test_should_query_connectionfilter():
|
@pytest.mark.parametrize("max_limit,does_count", [(None, True), (100, False)])
|
||||||
|
def test_should_query_connectionfilter(graphene_settings, max_limit, does_count):
|
||||||
|
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = max_limit
|
||||||
|
|
||||||
from ...filter import DjangoFilterConnectionField
|
from ...filter import DjangoFilterConnectionField
|
||||||
|
|
||||||
r1 = Reporter(last_name="ABA")
|
r1 = Reporter(last_name="ABA")
|
||||||
|
@ -224,7 +250,7 @@ def test_should_query_connectionfilter():
|
||||||
class Query(graphene.ObjectType):
|
class Query(graphene.ObjectType):
|
||||||
all_reporters = DjangoFilterConnectionField(ReporterType, fields=["last_name"])
|
all_reporters = DjangoFilterConnectionField(ReporterType, fields=["last_name"])
|
||||||
s = graphene.String(resolver=lambda *_: "S")
|
s = graphene.String(resolver=lambda *_: "S")
|
||||||
debug = graphene.Field(DjangoDebug, name="_debug")
|
debug = graphene.Field(DjangoDebug, name="__debug")
|
||||||
|
|
||||||
def resolve_all_reporters(self, info, **args):
|
def resolve_all_reporters(self, info, **args):
|
||||||
return Reporter.objects.all()
|
return Reporter.objects.all()
|
||||||
|
@ -238,7 +264,7 @@ def test_should_query_connectionfilter():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_debug {
|
__debug {
|
||||||
sql {
|
sql {
|
||||||
rawSql
|
rawSql
|
||||||
}
|
}
|
||||||
|
@ -252,6 +278,13 @@ def test_should_query_connectionfilter():
|
||||||
)
|
)
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
assert result.data["allReporters"] == expected["allReporters"]
|
assert result.data["allReporters"] == expected["allReporters"]
|
||||||
assert "COUNT" in result.data["_debug"]["sql"][0]["rawSql"]
|
if does_count:
|
||||||
|
assert len(result.data["__debug"]["sql"]) == 2
|
||||||
|
assert "COUNT" in result.data["__debug"]["sql"][0]["rawSql"]
|
||||||
query = str(Reporter.objects.all()[:1].query)
|
query = str(Reporter.objects.all()[:1].query)
|
||||||
assert result.data["_debug"]["sql"][1]["rawSql"] == query
|
assert result.data["__debug"]["sql"][1]["rawSql"] == query
|
||||||
|
else:
|
||||||
|
assert len(result.data["__debug"]["sql"]) == 1
|
||||||
|
assert "COUNT" not in result.data["__debug"]["sql"][0]["rawSql"]
|
||||||
|
query = str(Reporter.objects.all()[:1].query)
|
||||||
|
assert result.data["__debug"]["sql"][0]["rawSql"] == query
|
||||||
|
|
|
@ -127,12 +127,15 @@ class DjangoConnectionField(ConnectionField):
|
||||||
return connection._meta.node.get_queryset(queryset, info)
|
return connection._meta.node.get_queryset(queryset, info)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_connection(cls, connection, args, iterable):
|
def resolve_connection(cls, connection, args, iterable, max_limit=None):
|
||||||
iterable = maybe_queryset(iterable)
|
iterable = maybe_queryset(iterable)
|
||||||
|
# When slicing from the end, need to retrieve the iterable length.
|
||||||
|
if args.get("last"):
|
||||||
|
max_limit = None
|
||||||
if isinstance(iterable, QuerySet):
|
if isinstance(iterable, QuerySet):
|
||||||
_len = iterable.count()
|
_len = max_limit or iterable.count()
|
||||||
else:
|
else:
|
||||||
_len = len(iterable)
|
_len = max_limit or len(iterable)
|
||||||
connection = connection_from_list_slice(
|
connection = connection_from_list_slice(
|
||||||
iterable,
|
iterable,
|
||||||
args,
|
args,
|
||||||
|
@ -189,7 +192,9 @@ class DjangoConnectionField(ConnectionField):
|
||||||
# thus the iterable gets refiltered by resolve_queryset
|
# thus the iterable gets refiltered by resolve_queryset
|
||||||
# but iterable might be promise
|
# but iterable might be promise
|
||||||
iterable = queryset_resolver(connection, iterable, info, args)
|
iterable = queryset_resolver(connection, iterable, info, args)
|
||||||
on_resolve = partial(cls.resolve_connection, connection, args)
|
on_resolve = partial(
|
||||||
|
cls.resolve_connection, connection, args, max_limit=max_limit
|
||||||
|
)
|
||||||
|
|
||||||
if Promise.is_thenable(iterable):
|
if Promise.is_thenable(iterable):
|
||||||
return Promise.resolve(iterable).then(on_resolve)
|
return Promise.resolve(iterable).then(on_resolve)
|
||||||
|
|
|
@ -1084,6 +1084,48 @@ def test_should_resolve_get_queryset_connectionfields():
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
|
REPORTERS = [
|
||||||
|
dict(
|
||||||
|
first_name="First {}".format(i),
|
||||||
|
last_name="Last {}".format(i),
|
||||||
|
email="johndoe+{}@example.com".format(i),
|
||||||
|
a_choice=1,
|
||||||
|
)
|
||||||
|
for i in range(6)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_return_max_limit(graphene_settings):
|
||||||
|
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 4
|
||||||
|
reporters = [Reporter(**kwargs) for kwargs in REPORTERS]
|
||||||
|
Reporter.objects.bulk_create(reporters)
|
||||||
|
|
||||||
|
class ReporterType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = Reporter
|
||||||
|
interfaces = (Node,)
|
||||||
|
|
||||||
|
class Query(graphene.ObjectType):
|
||||||
|
all_reporters = DjangoConnectionField(ReporterType)
|
||||||
|
|
||||||
|
schema = graphene.Schema(query=Query)
|
||||||
|
query = """
|
||||||
|
query AllReporters {
|
||||||
|
allReporters {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = schema.execute(query)
|
||||||
|
assert not result.errors
|
||||||
|
assert len(result.data["allReporters"]["edges"]) == 4
|
||||||
|
|
||||||
|
|
||||||
def test_should_preserve_prefetch_related(django_assert_num_queries):
|
def test_should_preserve_prefetch_related(django_assert_num_queries):
|
||||||
class ReporterType(DjangoObjectType):
|
class ReporterType(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1130,7 +1172,7 @@ def test_should_preserve_prefetch_related(django_assert_num_queries):
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
schema = graphene.Schema(query=Query)
|
schema = graphene.Schema(query=Query)
|
||||||
with django_assert_num_queries(3) as captured:
|
with django_assert_num_queries(2) as captured:
|
||||||
result = schema.execute(query)
|
result = schema.execute(query)
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user