Skip to content

Commit

Permalink
fix: Avoid pagination failures when filtering connection by last with…
Browse files Browse the repository at this point in the history
…out before/after (#585)
  • Loading branch information
bellini666 authored Jul 14, 2024
1 parent 2897bab commit c2c3790
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
7 changes: 6 additions & 1 deletion strawberry_django/pagination.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
from typing import TYPE_CHECKING, List, Optional, TypeVar, Union

import strawberry
Expand Down Expand Up @@ -103,9 +104,13 @@ def apply_window_pagination(
partition_by=related_field_id,
),
)

if offset:
queryset = queryset.filter(_strawberry_row_number__gt=offset)
if limit >= 0:

# Limit == -1 means no limit. sys.maxsize is set by relay when paginating
# from the end to as a way to mimic a "not limit" as well
if limit >= 0 and limit != sys.maxsize:
queryset = queryset.filter(_strawberry_row_number__lte=offset + limit)

return queryset
Expand Down
51 changes: 50 additions & 1 deletion tests/test_pagination.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
from typing import List, cast

import pytest
Expand All @@ -6,7 +7,11 @@
from strawberry.types import ExecutionResult

import strawberry_django
from strawberry_django.pagination import OffsetPaginationInput, apply
from strawberry_django.pagination import (
OffsetPaginationInput,
apply,
apply_window_pagination,
)
from tests import models, utils
from tests.projects.faker import MilestoneFactory, ProjectFactory

Expand Down Expand Up @@ -96,3 +101,47 @@ def fruits(self, pagination: OffsetPaginationInput) -> List[Fruit]:
assert result.data["fruits"] == [
{"id": "1", "name": "strawberry"},
]


@pytest.mark.django_db(transaction=True)
def test_apply_window_pagination():
color = models.Color.objects.create(name="Red")

for i in range(10):
models.Fruit.objects.create(name=f"fruit{i}", color=color)

queryset = apply_window_pagination(
models.Fruit.objects.all(),
related_field_id="color_id",
offset=1,
limit=1,
)

assert queryset.count() == 1
fruit = queryset.get()
assert fruit.name == "fruit1"
assert fruit._strawberry_row_number == 2 # type: ignore
assert fruit._strawberry_total_count == 10 # type: ignore


@pytest.mark.parametrize("limit", [-1, sys.maxsize])
@pytest.mark.django_db(transaction=True)
def test_apply_window_pagination_with_no_limites(limit):
color = models.Color.objects.create(name="Red")

for i in range(10):
models.Fruit.objects.create(name=f"fruit{i}", color=color)

queryset = apply_window_pagination(
models.Fruit.objects.all(),
related_field_id="color_id",
offset=2,
limit=limit,
)

assert queryset.count() == 8
first_fruit = queryset.first()
assert first_fruit is not None
assert first_fruit.name == "fruit2"
assert first_fruit._strawberry_row_number == 3 # type: ignore
assert first_fruit._strawberry_total_count == 10 # type: ignore
3 changes: 2 additions & 1 deletion tests/test_queries.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io
import textwrap
from typing import List, Optional, cast
from unittest import mock

import pytest
import strawberry
Expand Down Expand Up @@ -312,4 +313,4 @@ def fruit(self) -> Fruit:
}
}
""")
assert result.data == {"fruit": {"colorId": 1, "name": "Banana"}}
assert result.data == {"fruit": {"colorId": mock.ANY, "name": "Banana"}}

0 comments on commit c2c3790

Please sign in to comment.