Skip to content

Commit

Permalink
Apply ordering of CIVs to API serializations (#3768)
Browse files Browse the repository at this point in the history
Ensures the ordering of CIVs on the rendered views is now also applied
to the API representations. This way, the order is the same when viewing
them within a view and CIRRUS.
  • Loading branch information
chrisvanrun authored Jan 13, 2025
1 parent 9c4dc34 commit d3d420d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
13 changes: 13 additions & 0 deletions app/grandchallenge/components/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ComponentInterface,
ComponentInterfaceValue,
)
from grandchallenge.components.templatetags.civ import sort_civs
from grandchallenge.core.guardian import filter_by_permission
from grandchallenge.uploads.models import UserUpload
from grandchallenge.workstation_configs.serializers import (
Expand Down Expand Up @@ -162,6 +163,17 @@ def validate(self, attrs):
return attrs


class SortedCIVSerializer(serializers.ListSerializer):
def to_representation(self, data):
iterable = (
data.all()
if isinstance(data, serializers.models.manager.BaseManager)
else data
)
sorted_data = sort_civs(iterable)
return super().to_representation(sorted_data)


class ComponentInterfaceValueSerializer(serializers.ModelSerializer):
# Serializes images in place rather than with hyperlinks for internal usage
image = SimpleImageSerializer(required=False)
Expand All @@ -170,6 +182,7 @@ class ComponentInterfaceValueSerializer(serializers.ModelSerializer):
class Meta:
model = ComponentInterfaceValue
fields = ["interface", "value", "file", "image", "pk"]
list_serializer_class = SortedCIVSerializer


class HyperlinkedComponentInterfaceValueSerializer(
Expand Down
4 changes: 2 additions & 2 deletions app/grandchallenge/components/templatetags/civ.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ def sort_civs(civs: Iterable[ComponentInterfaceValue]):
charts.append(v)
else:
values.append(v)
elif v.file:
elif v.interface.is_file_kind:
if v.interface.is_thumbnail_kind:
thumbnails.append(v)
else:
files.append(v)
elif v.image:
elif v.interface.is_image_kind:
images.append(v)
else:
residual.append(v)
Expand Down
58 changes: 57 additions & 1 deletion app/tests/components_tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
from grandchallenge.components.models import InterfaceKind
from grandchallenge.components.serializers import (
ComponentInterfaceValuePostSerializer,
ComponentInterfaceValueSerializer,
)
from tests.components_tests.factories import (
ComponentInterfaceFactory,
ComponentInterfaceValueFactory,
)
from tests.components_tests.factories import ComponentInterfaceFactory
from tests.factories import ImageFactory, UploadSessionFactory, UserFactory

TEST_DATA = {
Expand Down Expand Up @@ -468,3 +472,55 @@ def test_civ_post_image_valid(kind, rf):

# verify
assert serializer.is_valid()


@pytest.mark.django_db
def test_civ_serializer_list_ordering():

civs = [
ComponentInterfaceValueFactory(
interface=ComponentInterfaceFactory(
kind=InterfaceKind.InterfaceKindChoices.IMAGE,
store_in_database=False,
)
),
ComponentInterfaceValueFactory(
interface=ComponentInterfaceFactory(
kind=InterfaceKind.InterfaceKindChoices.THUMBNAIL_PNG,
store_in_database=False,
)
),
ComponentInterfaceValueFactory(
interface=ComponentInterfaceFactory(
kind=InterfaceKind.InterfaceKindChoices.ZIP,
store_in_database=False,
)
),
ComponentInterfaceValueFactory(
interface=ComponentInterfaceFactory(
kind=InterfaceKind.InterfaceKindChoices.STRING
),
value="bar",
),
ComponentInterfaceValueFactory(
interface=ComponentInterfaceFactory(
kind=InterfaceKind.InterfaceKindChoices.CHART
),
value="foo",
),
]

serializer = ComponentInterfaceValueSerializer(many=True)

produced_order = [
civ["interface"]["kind"]
for civ in serializer.to_representation(data=civs)
]

assert produced_order == [
InterfaceKind.InterfaceKindChoices.STRING.label,
InterfaceKind.InterfaceKindChoices.THUMBNAIL_PNG.label,
InterfaceKind.InterfaceKindChoices.CHART.label,
InterfaceKind.InterfaceKindChoices.ZIP.label,
InterfaceKind.InterfaceKindChoices.IMAGE.label,
]

0 comments on commit d3d420d

Please sign in to comment.