Skip to main content

Sorters

Key concepts

Sorters allow returning elements that are ordered based on specific criteria. This document describes how to add a sorter to the query resolver.

Add sorter to query resolver

Step 1: Create new sort field

To create a new sort field, add sorters.py file in the target graphql directory. Inside this directory, create a GraphQL enum with members representing the options that can be used for sorting and a description property explaining how to use the field.

Let's see an example:

import graphene


class ExampleSortField(graphene.Enum):
NAME = ["name", "slug"]
VISIBILITY = ["is_published", "name", "slug"]

@property
def description(self):
if self.name in ExampleSortField.__enum__._member_names_:
sort_name = self.name.lower().replace("_", " ")
return f"Sort Example by {sort_name}."
raise ValueError("Unsupported enum value: %s" % self.value)

GraphQL field name defines the schema field, which can be used to sort elements, and the value defines the list of model fields that will be used for sorting. The list can contain multiple elements, each consecutive field used when the values of the previous one are tied.

In the above example, if elements sorted by NAME have the same value in the name field, they will be sorted by the value of the slug field.

Step 2: Create Sort Input

In the same file create a SortInputObjectType. In its Meta class, define sort_enum which corresponds to just created sorted enum and type_name which is used to create sorter description.

from saleor.graphql.core.types import SortInputObjectType


class ExampleSortingInput(SortInputObjectType):
class Meta:
sort_enum = ExampleSortField
type_name = "examples"

Step 3: Add sorter to query

Define the sort_by field in your target query resolver in the schema.py file. Make sure that resolver use BaseDjangoConnectionField or another type which inherits from this. Here is an example:

import graphene
from saleor.graphql.core.field import BaseDjangoConnectionField


class ExampleQueries(graphene.ObjectType):
examples = BaseDjangoConnectionField(
Example,
description="List of the examples.",
sort_by=ExampleSortingInput(description="Sorting options for examples.")
)

Add custom sorter

When defining sorter apart from a model field you can define a custom sort field, and use it like other fields.

Step 1: Define a static method in your sorter field

The method name must follow the format qs_with_new_field where new_field corresponds to the custom field you want to sort your queryset with. The method must take a queryset as an argument and return a queryset with the annotated new field. Please notice that the new field name from the method name must be the same as the annotated field.

class ExampleSortField(graphene.Enum):
NAME = ["name", "slug"]
VISIBILITY = ["is_published", "name", "slug"]

@property
def description(self):
if self.name in ExampleSortField.__enum__._member_names_:
sort_name = self.name.lower().replace("_", " ")
return f"Sort Example by {sort_name}."
raise ValueError("Unsupported enum value: %s" % self.value)

@staticmethod
def qs_with_item_count(queryset: Queryset) -> Queryset:
return queryset.annotate(item_count=Count("item"))

Step 2: Use the field in a sort field definition

The next step is using it in sort field definition as a normal model field. Notice that value in the list must be the same as annotated field name.

class ExampleSortField(graphene.Enum):
NAME = ["name", "slug"]
VISIBILITY = ["is_published", "name", "slug"]
ITEM_COUNT = ["item_count"]

@property
def description(self):
if self.name in ExampleSortField.__enum__._member_names_:
sort_name = self.name.lower().replace("_", " ")
return f"Sort Example by {sort_name}."
raise ValueError("Unsupported enum value: %s" % self.value)

@staticmethod
def qs_with_item_count(queryset: Queryset) -> Queryset:
return queryset.annotate(item_count=Count("item"))