mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-25 19:14:11 +03:00
fix: backward pagination indexing error when using bigger last argument than total number of elements (#1344)
Co-authored-by: Thomas Leonard <thomas@loftorbital.com>
This commit is contained in:
parent
5f1731dca3
commit
2aeb86ba3b
|
@ -146,36 +146,38 @@ class DjangoConnectionField(ConnectionField):
|
||||||
iterable = maybe_queryset(iterable)
|
iterable = maybe_queryset(iterable)
|
||||||
|
|
||||||
if isinstance(iterable, QuerySet):
|
if isinstance(iterable, QuerySet):
|
||||||
list_length = iterable.count()
|
array_length = iterable.count()
|
||||||
else:
|
else:
|
||||||
list_length = len(iterable)
|
array_length = len(iterable)
|
||||||
list_slice_length = (
|
array_slice_length = (
|
||||||
min(max_limit, list_length) if max_limit is not None else list_length
|
min(max_limit, array_length) if max_limit is not None else array_length
|
||||||
)
|
)
|
||||||
|
|
||||||
# If after is higher than list_length, connection_from_list_slice
|
# If after is higher than list_length, connection_from_list_slice
|
||||||
# would try to do a negative slicing which makes django throw an
|
# would try to do a negative slicing which makes django throw an
|
||||||
# AssertionError
|
# AssertionError
|
||||||
after = min(get_offset_with_default(args.get("after"), -1) + 1, list_length)
|
slice_start = min(
|
||||||
|
get_offset_with_default(args.get("after"), -1) + 1, array_length
|
||||||
|
)
|
||||||
|
|
||||||
if max_limit is not None and args.get("first", None) is None:
|
if max_limit is not None and args.get("first", None) is None:
|
||||||
if args.get("last", None) is not None:
|
if args.get("last", None) is not None:
|
||||||
after = list_length - args["last"]
|
slice_start = max(array_length - args["last"], 0)
|
||||||
else:
|
else:
|
||||||
args["first"] = max_limit
|
args["first"] = max_limit
|
||||||
|
|
||||||
connection = connection_from_array_slice(
|
connection = connection_from_array_slice(
|
||||||
iterable[after:],
|
iterable[slice_start:],
|
||||||
args,
|
args,
|
||||||
slice_start=after,
|
slice_start=slice_start,
|
||||||
array_length=list_length,
|
array_length=array_length,
|
||||||
array_slice_length=list_slice_length,
|
array_slice_length=array_slice_length,
|
||||||
connection_type=partial(connection_adapter, connection),
|
connection_type=partial(connection_adapter, connection),
|
||||||
edge_type=connection.Edge,
|
edge_type=connection.Edge,
|
||||||
page_info_type=page_info_adapter,
|
page_info_type=page_info_adapter,
|
||||||
)
|
)
|
||||||
connection.iterable = iterable
|
connection.iterable = iterable
|
||||||
connection.length = list_length
|
connection.length = array_length
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -1593,3 +1593,78 @@ def test_connection_should_allow_offset_filtering_with_after():
|
||||||
"allReporters": {"edges": [{"node": {"firstName": "Jane", "lastName": "Roe"}},]}
|
"allReporters": {"edges": [{"node": {"firstName": "Jane", "lastName": "Roe"}},]}
|
||||||
}
|
}
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_connection_should_succeed_if_last_higher_than_number_of_objects():
|
||||||
|
class ReporterType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = Reporter
|
||||||
|
interfaces = (Node,)
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
class Query(graphene.ObjectType):
|
||||||
|
all_reporters = DjangoConnectionField(ReporterType)
|
||||||
|
|
||||||
|
schema = graphene.Schema(query=Query)
|
||||||
|
query = """
|
||||||
|
query ReporterPromiseConnectionQuery ($last: Int) {
|
||||||
|
allReporters(last: $last) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = schema.execute(query, variable_values=dict(last=2))
|
||||||
|
assert not result.errors
|
||||||
|
expected = {"allReporters": {"edges": []}}
|
||||||
|
assert result.data == expected
|
||||||
|
|
||||||
|
Reporter.objects.create(first_name="John", last_name="Doe")
|
||||||
|
Reporter.objects.create(first_name="Some", last_name="Guy")
|
||||||
|
Reporter.objects.create(first_name="Jane", last_name="Roe")
|
||||||
|
Reporter.objects.create(first_name="Some", last_name="Lady")
|
||||||
|
|
||||||
|
result = schema.execute(query, variable_values=dict(last=2))
|
||||||
|
assert not result.errors
|
||||||
|
expected = {
|
||||||
|
"allReporters": {
|
||||||
|
"edges": [
|
||||||
|
{"node": {"firstName": "Jane", "lastName": "Roe"}},
|
||||||
|
{"node": {"firstName": "Some", "lastName": "Lady"}},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result.data == expected
|
||||||
|
|
||||||
|
result = schema.execute(query, variable_values=dict(last=4))
|
||||||
|
assert not result.errors
|
||||||
|
expected = {
|
||||||
|
"allReporters": {
|
||||||
|
"edges": [
|
||||||
|
{"node": {"firstName": "John", "lastName": "Doe"}},
|
||||||
|
{"node": {"firstName": "Some", "lastName": "Guy"}},
|
||||||
|
{"node": {"firstName": "Jane", "lastName": "Roe"}},
|
||||||
|
{"node": {"firstName": "Some", "lastName": "Lady"}},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result.data == expected
|
||||||
|
|
||||||
|
result = schema.execute(query, variable_values=dict(last=20))
|
||||||
|
assert not result.errors
|
||||||
|
expected = {
|
||||||
|
"allReporters": {
|
||||||
|
"edges": [
|
||||||
|
{"node": {"firstName": "John", "lastName": "Doe"}},
|
||||||
|
{"node": {"firstName": "Some", "lastName": "Guy"}},
|
||||||
|
{"node": {"firstName": "Jane", "lastName": "Roe"}},
|
||||||
|
{"node": {"firstName": "Some", "lastName": "Lady"}},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result.data == expected
|
||||||
|
|
Loading…
Reference in New Issue
Block a user