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"))