mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 09:57:53 +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