Basic Sorting
This guide covers single-field sorting with SortSpec for both in-memory collections and SQLAlchemy queries.
SortSpec
Create a SortSpec to describe how to sort:
from pypaginate import SortSpec, SortDirection, NullsPosition
# Sort by name ascending (defaults)
SortSpec(field="name")
# Sort by created_at descending, nulls last
SortSpec(field="created_at", direction=SortDirection.DESC, nulls=NullsPosition.LAST)
In-Memory Sorting
Using SortEngine
SortEngine sorts Python sequences directly:
from pypaginate import SortSpec, SortDirection
from pypaginate.sorting.engine import SortEngine
engine = SortEngine()
products = [
{"name": "Widget", "price": 29.99},
{"name": "Gadget", "price": 49.99},
{"name": "Gizmo", "price": 19.99},
]
# Sort by price ascending
sorted_products = engine.apply(products, [
SortSpec(field="price"),
])
# [Gizmo(19.99), Widget(29.99), Gadget(49.99)]
# Sort by price descending
sorted_products = engine.apply(products, [
SortSpec(field="price", direction=SortDirection.DESC),
])
# [Gadget(49.99), Widget(29.99), Gizmo(19.99)]
Using MemorySortBackend
MemorySortBackend satisfies the SortBackend protocol for pipeline use:
from pypaginate import SortSpec, SortDirection
from pypaginate.adapters.memory import MemorySortBackend
backend = MemorySortBackend()
sorted_items = backend.apply_sorting(products, [
SortSpec(field="price", direction=SortDirection.DESC),
])
Null Value Handling
NullsPosition controls where None values appear in sorted results:
from pypaginate import SortSpec, SortDirection, NullsPosition
from pypaginate.sorting.engine import SortEngine
engine = SortEngine()
products = [
{"name": "Widget", "stock": None},
{"name": "Gadget", "stock": 25},
{"name": "Gizmo", "stock": 50},
]
# Nulls first
sorted_products = engine.apply(products, [
SortSpec(field="stock", nulls=NullsPosition.FIRST),
])
# [Widget(None), Gadget(25), Gizmo(50)]
# Nulls last (default)
sorted_products = engine.apply(products, [
SortSpec(field="stock", nulls=NullsPosition.LAST),
])
# [Gadget(25), Gizmo(50), Widget(None)]
Null positioning is independent of sort direction:
# Descending sort with nulls last
sorted_products = engine.apply(products, [
SortSpec(field="stock", direction=SortDirection.DESC, nulls=NullsPosition.LAST),
])
# [Gizmo(50), Gadget(25), Widget(None)]
SQLAlchemy Sorting
SQLAlchemySortBackend translates SortSpec to ORDER BY clauses:
from sqlalchemy import select
from pypaginate import SortSpec, SortDirection, NullsPosition
from pypaginate.adapters.sqlalchemy import SQLAlchemySortBackend
backend = SQLAlchemySortBackend()
stmt = select(Product)
sorted_stmt = backend.apply_sorting(stmt, [
SortSpec(field="price", direction=SortDirection.DESC, nulls=NullsPosition.LAST),
])
# SELECT * FROM product ORDER BY price DESC NULLS LAST
The backend generates proper SQLAlchemy expressions:
SortDirection.ASC->column.asc()SortDirection.DESC->column.desc()NullsPosition.FIRST->.nulls_first()NullsPosition.LAST->.nulls_last()
Pipeline Usage
Pass sorting specs to SyncPipeline.execute() or AsyncPipeline.execute() via the sorting= parameter. See Multi-Column Sorting for pipeline examples with sorting, filtering, and pagination combined.
Common Patterns
Sort by Date
from pypaginate import SortSpec, SortDirection
# Most recent first
SortSpec(field="created_at", direction=SortDirection.DESC)
# Oldest first
SortSpec(field="created_at", direction=SortDirection.ASC)
Alphabetical Sort
# A-Z
SortSpec(field="name", direction=SortDirection.ASC)
# Z-A
SortSpec(field="name", direction=SortDirection.DESC)
Numeric Sort
# Highest price first
SortSpec(field="price", direction=SortDirection.DESC)
# Lowest score first
SortSpec(field="score", direction=SortDirection.ASC)
Error Handling
SortError is raised when field values cannot be compared (e.g., mixed types):
from pypaginate import SortError, SortSpec
from pypaginate.sorting.engine import SortEngine
engine = SortEngine()
items = [{"val": "abc"}, {"val": 123}]
try:
engine.apply(items, [SortSpec(field="val")])
except SortError as e:
print(f"Sort error: {e}")
Next Steps
Multi-Column Sorting – Sort by multiple fields with priority