Skip to main content

strawberry-django-aggregates

Hasura-shape aggregations over Django querysets in Strawberry GraphQL.

count · count_distinct · sum · avg · min · max · stddev · variance · bool_and · bool_or · array_agg · string_agg — composed with multi-level group_by, having filters, and ordering on aggregate aliases. Inspired by Hasura's <table>_aggregate, PostGraphile's pg-aggregates, and Odoo 18's _read_group. Built for strawberry-django over PostgreSQL and SQLite.

from decimal import Decimal
from datetime import datetime
from strawberry import auto
import strawberry, strawberry_django
from strawberry_django_aggregates import AggregateBuilder

from .models import Order

@strawberry_django.type(Order)
class OrderType:
    id: auto
    customer: "CustomerType"
    total: Decimal
    status: str
    created_at: datetime

# One call wires count/sum/avg/min/max + group_by + having into the schema:
order_aggs = AggregateBuilder(
    model=Order,
    aggregate_fields=["total"],
    group_by_fields=["customer", "status", "created_at"],
).build()

@strawberry.type
class Query:
    orders_aggregate = order_aggs.aggregate_field
    orders_group_by  = order_aggs.group_by_field

Generates a fully-typed GraphQL surface:

type Query {
  ordersAggregate(filter: OrderFilter): OrderAggregate!
  ordersGroupBy(
    filter:    OrderFilter
    groupBy:   [OrderGroupBySpec!]!
    having:    OrderHaving
    orderBy:   [OrderGroupOrder!]
    pagination: OffsetPagination
  ): OrderGroupedResult!
}

type OrderAggregate {
  count:           Int!
  countDistinct(field: OrderCountableField!): Int!
  sum:             OrderSumFields
  avg:             OrderAvgFields
  min:             OrderMinFields
  max:             OrderMaxFields
  stddev:          OrderStddevFields    # Postgres only
  variance:        OrderVarianceFields  # Postgres only
}

type OrderGrouped {
  key:   OrderGroupKey!   # composite — every requested groupBy field present
  count: Int!
  sum:   OrderSumFields
  # ... no recursive subgroups field — flat results
}

Features

  • Hasura-canonical schema shape. <Model>Aggregate { count, countDistinct, sum, avg, min, max, stddev, variance, boolAnd, boolOr, arrayAgg, stringAgg }.
  • Odoo-grade group-by. Multi-level via composite keys (flat result rows), dual date-granularity tracks (date_trunc returning DateTime AND date_part::int returning Int), timezone-correct bucketing.
  • HAVING with aggregate aliases. { countGt: 5, sumTotalGt: 1000 } — typed inputs generated per measure.
  • Ordering on aggregates. [{ field: "total:sum", direction: DESC }] — fail-loud on unknown terms (Odoo's pre-17 silent-drop bug avoided).
  • Standalone backend primitive. compute_aggregation(qs, group_by, aggregates, having, order_by, ...) is callable from any Python context — DRF view, Celery task, admin script, MCP tool — not just GraphQL resolvers.
  • Computed rows. make_row_model(...) declares the columns of non-table rows, and compute_row_aggregation(rows, model=..., ...) groups them in memory with the same types, translators, key shapers and result rows as a queryset (SPEC § 20).
  • Composable group-key projection. A custom grouped envelope can pass the same group_by_expressions mapping to compute_aggregation and AggregateBuilder.count_groups for selected to-one scalar/date axes. Native aliases, temporal bucketing, HAVING, rows, and exact counts stay aligned; unsupported axes fail loud.
  • Exact group cardinality. AggregateBuilder.count_groups(...) returns the database-side group count before pagination for custom grouped envelopes, including filters, granularity, JSON paths, and HAVING.
  • Determinism. Type generation produces byte-identical SDL for the same inputs.
  • No magic. Every operator, every granularity, every type is whitelisted.

Non-goals

  • Cross-database aggregation. PostgreSQL + SQLite only. SQLite degrades gracefully on array_agg/string_agg/stddev/variance — those operators raise OperatorNotSupportedError at resolver entry.
  • Auto-traversal of one-to-many / many-to-many for measures. This is the silent row-multiplication footgun Odoo refuses to ship; we follow. array_agg is the explicit escape hatch.
  • Permission integration. The library expects a pre-scoped queryset — the caller has already applied accessible_by(user) or equivalent. This keeps the library compatible with django-guardian, django-rules, django-rebac (when shipped), or hand-rolled permission systems.

Status

Beta (v0.10.0). The schema shape, operator vocabulary, and compute_aggregation signature are stable for early adopters, but minor-level iteration is still expected before a 1.0 stability commitment — see docs/SPEC.md § 16. Runtime: Python 3.14, Django 6.0.

Documentation

  • Full contract: docs/SPEC.md — operator catalog, granularity tracks, HAVING semantics, ordering rules, timezone handling, and the Odoo-derived footgun audit.
  • Naming and wire vocabulary: docs/TERMINOLOGY.md
  • Contributor quality gate: CONTRIBUTING.md

License

BSD-3-Clause.

Metadata

Release files for strawberry-django-aggregates 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for strawberry-django-aggregates 0.14.0
File Size Uploaded
strawberry_django_aggregates-0.14.0.tar.gz 179.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for strawberry-django-aggregates 0.14.0
File Interpreter ABI Platform
strawberry_django_aggregates-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 294.6 kB

Release files / strawberry_django_aggregates-0.14.0.tar.gz

Download URL strawberry_django_aggregates-0.14.0.tar.gz
Size 179.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a837203d4299a6d80ccf1b4880f3c5e402f2c9e9e73ecc9852859403805a17fc
BLAKE2b-256 checksum
How to use checksums
ca3e739c73f072e4d43d68b4918319f76fbb6d23420420152a9b1cf27b247c39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / strawberry_django_aggregates-0.14.0-py3-none-any.whl

Download URL strawberry_django_aggregates-0.14.0-py3-none-any.whl
Size 115.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29a5652b679aa0897f28096d49805e07453537d57cfe96b3d8680a8a3dd7e81b
BLAKE2b-256 checksum
How to use checksums
4815513e15531c95e737f53f565bb27277b7b05f16a503df7cb2cb51372ff363
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.14.0 This release

2 release files

0.13.0

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page