Ordering & Pagination
Control the sort order and size of your result sets.
Ordering
# Ascending
await Post.objects.order_by("title")
# Descending (prefix with -)
await Post.objects.order_by("-views")
# Multiple fields
await Post.objects.order_by("-views", "title")
# Default ordering from Meta
class Post(Model):
class Meta:
ordering = ["-created_at"] # Applied automatically
Limit & Offset
# First 10
await Post.objects.limit(10)
# Skip 20, take 10
await Post.objects.limit(10).offset(20)
Slicing
QuerySets support Python slice syntax:
# First 10
await Post.objects.all()[:10]
# Page 2 (items 10-19)
await Post.objects.all()[10:20]
# Single item by index
third = await Post.objects.all()[2]
warning
Negative indexing (qs[-1]) is not supported — use .order_by().first() instead.
Pagination Pattern
async def paginate(queryset, page: int = 1, per_page: int = 20):
offset = (page - 1) * per_page
items = await queryset.limit(per_page).offset(offset)
total = await queryset.count()
return {
"items": items,
"total": total,
"page": page,
"pages": (total + per_page - 1) // per_page,
}
# Usage
result = await paginate(Post.objects.filter(active=True), page=2, per_page=10)
Distinct
# SELECT DISTINCT
await Post.objects.filter(active=True).distinct()
Next Steps
→ Aggregations — Count, Sum, Avg, and more