Django ORM PostgreSQL

Django ORM PostgreSQL

Explore django orm postgresql code snippets and tutorials

Django ORM PostgreSQL

Dates & standard aggregates (Count/Avg/Min/Max/Sum, ExtractYear)

aggregate() collapses the whole queryset into a single row of numbers.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# ======================================================================
# `aggregate()` collapses the whole queryset into a single row of numbers. To
# get one row *per group* instead, use `values(...)` (the GROUP BY) followed by
# `annotate(...)`. `ExtractYear` pulls the year out of a datetime so we can
# count books per year.
# ======================================================================

# ----------------------------------------------------------------------
# aggregate over all books
# ----------------------------------------------------------------------

# Django:
Book.objects.aggregate(
    n=Count("id"), avg=Avg("price"),
    lo=Min("price"), hi=Max("price"), total=Sum("price"),
)

# SQL:
#   SELECT COUNT("examples_book"."id") AS "n", AVG("examples_book"."price") AS "avg", MIN("examples_book"."price") AS "lo", MAX("examples_book"."price") AS "hi", SUM("examples_book"."price") AS "total"
#   FROM "examples_book"

# Result:
#   n=4  avg=15.87  min=0.00  max=29.00  total=63.49

# ----------------------------------------------------------------------
# books per publication year
# ----------------------------------------------------------------------

# Django:
Book.objects.annotate(y=ExtractYear("published")) \
    .values("y").annotate(n=Count("id")).order_by("y")

# SQL:
#   SELECT EXTRACT(YEAR
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "y", COUNT("examples_book"."id") AS "n"
#   FROM "examples_book"
#   GROUP BY 1
#   ORDER BY 1 ASC

# Result:
#   1937: 1
#   1954: 1
#   1997: 1
#   2026: 1
Django ORM PostgreSQL

Comparison & conversion (Greatest, Least, NullIf, Cast, Collate, KT)

Greatest/Least pick across columns/values, NullIf(a, b) returns NULL when a==b, Cast changes a value's type, Collate applies a collation to one expression, and KT extracts a JSON path as text.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# ======================================================================
# `Greatest`/`Least` pick across columns/values, `NullIf(a, b)` returns NULL
# when a==b, `Cast` changes a value's type, `Collate` applies a collation to one
# expression, and `KT` extracts a JSON path as text.
# ======================================================================

# ----------------------------------------------------------------------
# Greatest / Least / Cast / KT over 'Harry Potter'
# ----------------------------------------------------------------------

# Django:
money = DecimalField(max_digits=8, decimal_places=2)
Book.objects.filter(title="Harry Potter").annotate(
    greatest=Greatest("price", Value(25), output_field=money),
    least=Least("price", Value(25), output_field=money),
    as_int=Cast("price", output_field=IntegerField()),
    stock=KT("data__specs__stock"),
).values("greatest", "least", "as_int", "stock")

# SQL:
#   SELECT GREATEST("examples_book"."price", 25) AS "greatest", LEAST("examples_book"."price", 25) AS "least", ("examples_book"."price")::integer AS "as_int", ("examples_book"."data" #>> '{specs,stock}') AS "stock"
#   FROM "examples_book"
#   WHERE "examples_book"."title" = 'Harry Potter'
#   ORDER BY "examples_book"."id" ASC
#   LIMIT 1

# Result:
#   Greatest(price, 25) -> 25
#   Least(price, 25)    -> 19.99
#   Cast(price -> int)  -> 20
#   KT(data.specs.stock)-> '12'  (json value as text)

# ----------------------------------------------------------------------
# NullIf(bio, 'British author') -> NULL when equal
# ----------------------------------------------------------------------

# Django:
Author.objects.annotate(x=NullIf("bio", Value("British author"), output_field=TextField())).values_list("name", "x")

# SQL:
#   SELECT "examples_author"."name" AS "name", NULLIF("examples_author"."bio", 'British author') AS "x"
#   FROM "examples_author"

# Result:
#   J. K. Rowling: None
#   J. R. R. Tolkien: None
#   Karl Müller: 'Schriftsteller'

# ----------------------------------------------------------------------
# Collate(name, 'C') then order by it
# ----------------------------------------------------------------------

# Django:
Author.objects.order_by(Collate("name", "C")).values_list("name", flat=True)

# SQL:
#   SELECT "examples_author"."name" AS "name"
#   FROM "examples_author"
#   ORDER BY "examples_author"."name" COLLATE "C" ASC

# Result:
#   J. K. Rowling
#   J. R. R. Tolkien
#   Karl Müller
Django ORM PostgreSQL

Date / time functions

Date handling over one book's published timestamp.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# ======================================================================
# Date handling over one book's `published` timestamp. `Extract*` pulls a
# component (year, month, day, weekday, quarter); `Trunc*` rounds a timestamp
# down to a unit (`date_trunc`); `Now()` is the statement timestamp.
# ======================================================================

# ----------------------------------------------------------------------
# date parts & truncation over the 2026 book
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(title="Postgres for Authors").annotate(
    year=ExtractYear("published"), month=ExtractMonth("published"),
    day=ExtractDay("published"), weekday=ExtractWeekDay("published"),
    quarter=ExtractQuarter("published"), week=ExtractWeek("published"),
    isoyear=ExtractIsoYear("published"), isodow=ExtractIsoWeekDay("published"),
    hour=ExtractHour("published"), minute=ExtractMinute("published"),
    second=ExtractSecond("published"),
    tmonth=TruncMonth("published"), tyear=TruncYear("published"),
    tday=TruncDay("published"), tweek=TruncWeek("published"),
    tquarter=TruncQuarter("published"), thour=TruncHour("published"),
    tminute=TruncMinute("published"), tsecond=TruncSecond("published"),
    ttime=TruncTime("published"), now=Now(),
)

# SQL:
#   SELECT EXTRACT(YEAR
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "year", EXTRACT(MONTH
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "month", EXTRACT(DAY
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "day", EXTRACT(DOW
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') + 1 AS "weekday", EXTRACT(QUARTER
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "quarter", EXTRACT(WEEK
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "week", EXTRACT(ISOYEAR
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "isoyear", EXTRACT(ISODOW
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "isodow", EXTRACT(HOUR
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "hour", EXTRACT(MINUTE
#   FROM "examples_book"."published" AT TIME ZONE 'UTC') AS "minute", EXTRACT(SECOND
#   FROM DATE_TRUNC('second', "examples_book"."published" AT TIME ZONE 'UTC')) AS "second", DATE_TRUNC('month', "examples_book"."published" AT TIME ZONE 'UTC') AS "tmonth", DATE_TRUNC('year', "examples_book"."published" AT TIME ZONE 'UTC') AS "tyear", DATE_TRUNC('day', "examples_book"."published" AT TIME ZONE 'UTC') AS "tday", DATE_TRUNC('week', "examples_book"."published" AT TIME ZONE 'UTC') AS "tweek", DATE_TRUNC('quarter', "examples_book"."published" AT TIME ZONE 'UTC') AS "tquarter", DATE_TRUNC('hour', "examples_book"."published" AT TIME ZONE 'UTC') AS "thour", DATE_TRUNC('minute', "examples_book"."published" AT TIME ZONE 'UTC') AS "tminute", DATE_TRUNC('second', "examples_book"."published" AT TIME ZONE 'UTC') AS "tsecond", ("examples_book"."published" AT TIME ZONE 'UTC')::time AS "ttime", STATEMENT_TIMESTAMP() AS "now"
#   FROM "examples_book"
#   WHERE "examples_book"."title" = 'Postgres for Authors'
#   ORDER BY "examples_book"."id" ASC
#   LIMIT 1

# Result:
#   ExtractYear      -> 2026
#   ExtractMonth     -> 1
#   ExtractDay       -> 15
#   ExtractWeekDay   -> 5  (1=Sun .. 7=Sat)
#   ExtractISOWeekDay-> 4  (1=Mon .. 7=Sun)
#   ExtractQuarter   -> 1
#   ExtractWeek      -> 3
#   ExtractISOYear   -> 2026
#   ExtractHour      -> 0
#   ExtractMinute    -> 0
#   ExtractSecond    -> 0
#   TruncMonth       -> 2026-01-01
#   TruncYear        -> 2026-01-01
#   TruncDay         -> 2026-01-15
#   TruncWeek        -> 2026-01-12
#   TruncQuarter     -> 2026-01-01
#   TruncHour        -> 2026-01-15 00:00
#   TruncMinute      -> 2026-01-15 00:00
#   TruncSecond      -> 2026-01-15 00:00:00
#   TruncTime        -> 00:00:00
#   Now()            -> 2026-05-22 19:01 UTC
Django ORM PostgreSQL

Math functions

Numeric functions over one book's price/pages: Abs, Ceil, Floor, Round(x, n), Sign, Mod, Power, Sqrt, Exp, Ln, Log(base, x).

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# ======================================================================
# Numeric functions over one book's price/pages: `Abs`, `Ceil`, `Floor`,
# `Round(x, n)`, `Sign`, `Mod`, `Power`, `Sqrt`, `Exp`, `Ln`, `Log(base, x)`.
# All evaluated by PostgreSQL.
# ======================================================================

# ----------------------------------------------------------------------
# numeric functions over the LOTR row
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(title="The Lord of the Rings").annotate(
    absv=Abs("price"), ceil=Ceil("price"), floor=Floor("price"),
    round1=Round("price", 1), sign=Sign("price"), mod=Mod("pages", Value(100)),
    power=Power("price", Value(2)), sqrt=Sqrt("pages"), exp=Exp(Value(1)),
    ln=Ln("pages"), log10=Log(Value(10), "pages"), pi=Pi(),
    sin=Sin(Value(1.0)), cos=Cos(Value(1.0)), tan=Tan(Value(1.0)),
    cot=Cot(Value(1.0)), asin=ASin(Value(0.5)), acos=ACos(Value(0.5)),
    atan=ATan(Value(1.0)), atan2=ATan2(Value(1.0), Value(1.0)),
    degrees=Degrees(Value(3.14159265)), radians=Radians(Value(180.0)),
    rand=Random(),
)

# SQL:
#   SELECT ABS("examples_book"."price") AS "absv", CEILING("examples_book"."price") AS "ceil", FLOOR("examples_book"."price") AS "floor", ROUND("examples_book"."price", 1) AS "round1", SIGN("examples_book"."price") AS "sign", MOD("examples_book"."pages", 100) AS "mod", POWER("examples_book"."price", 2) AS "power", SQRT("examples_book"."pages") AS "sqrt", EXP(1) AS "exp", LN("examples_book"."pages") AS "ln", LOG(10, "examples_book"."pages") AS "log10", PI() AS "pi", SIN(1.0) AS "sin", COS(1.0) AS "cos", TAN(1.0) AS "tan", COT(1.0) AS "cot", ASIN(0.5) AS "asin", ACOS(0.5) AS "acos", ATAN(1.0) AS "atan", ATAN2(1.0, 1.0) AS "atan2", DEGREES(3.14159265) AS "degrees", RADIANS(180.0) AS "radians", RANDOM() AS "rand"
#   FROM "examples_book"
#   WHERE "examples_book"."title" = 'The Lord of the Rings'
#   ORDER BY "examples_book"."id" ASC
#   LIMIT 1

# Result:
#   Abs(price)        -> 29.00
#   Ceil(price)       -> 29
#   Floor(price)      -> 29
#   Round(price, 1)   -> 29.0
#   Sign(price)       -> 1
#   Mod(pages, 100)   -> 78.0
#   Power(price, 2)   -> 841.00000000000000
#   Sqrt(pages)       -> 34.3220
#   Exp(1)            -> 2.7183
#   Ln(pages)         -> 7.0716
#   Log(10, pages)    -> 3.0711
#   Pi()              -> 3.14159
#   Sin(1)            -> 0.8415
#   Cos(1)            -> 0.5403
#   Tan(1)            -> 1.5574
#   Cot(1)            -> 0.6421
#   ASin(0.5)         -> 0.5236
#   ACos(0.5)         -> 1.0472
#   ATan(1)           -> 0.7854  (= π/4)
#   ATan2(1, 1)       -> 0.7854  (= π/4)
#   Degrees(π)        -> 180.00
#   Radians(180)      -> 3.1416  (= π)
#   Random()          -> 0.3992  (0..1)
Django ORM PostgreSQL

Text functions

A gallery of string functions, each computed in the database over one book's title.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# ======================================================================
# A gallery of string functions, each computed in the database over one book's
# title. They map directly to SQL: `Lower`/`Upper`, `Length`, `Substr`,
# `Left`/`Right`, `LPad`, `Trim`, `Replace`, `Reverse`, `StrIndex` (position),
# `Repeat`, `MD5`/`SHA256` hashing, and `Concat`.
# ======================================================================

# ----------------------------------------------------------------------
# string functions over 'The Hobbit'
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(title="The Hobbit").annotate(
    lower=Lower("title"), upper=Upper("title"), length=Length("title"),
    substr=Substr("title", 1, 3), left=Left("title", 3), right=Right("title", 3),
    lpad=LPad("title", 18, Value("·")), rpad=RPad("title", 18, Value("·")),
    trimmed=Trim(Value("   spaced   ")), ltrim=LTrim(Value("   x")), rtrim=RTrim(Value("x   ")),
    replaced=Replace("title", Value("o"), Value("0")), reversed=Reverse("title"),
    idx=StrIndex("title", Value("Hobbit")), repeat=Repeat(Value("ab"), 3),
    chr=Chr(Value(65)), ord=Ord("title"),
    md5=MD5("title"), sha=SHA256("title"),
    concat=Concat("title", Value(" — "), "author__name"),
)

# SQL:
#   SELECT LOWER("examples_book"."title") AS "lower", UPPER("examples_book"."title") AS "upper", LENGTH("examples_book"."title") AS "length", SUBSTRING("examples_book"."title", 1, 3) AS "substr", LEFT("examples_book"."title", 3) AS "left", RIGHT("examples_book"."title", 3) AS "right", LPAD("examples_book"."title", 18, '·') AS "lpad", TRIM('   spaced   ') AS "trimmed", REPLACE("examples_book"."title", 'o', '0') AS "replaced", REVERSE("examples_book"."title") AS "reversed", STRPOS("examples_book"."title", 'Hobbit') AS "idx", REPEAT('ab', 3) AS "repeat", MD5("examples_book"."title") AS "md5", ENCODE(DIGEST("examples_book"."title", 'sha256'), 'hex') AS "sha", (COALESCE("examples_book"."title", '') || COALESCE((COALESCE(' — ', '') || COALESCE("examples_author"."name", '')), '')) AS "concat", RPAD("examples_book"."title", 18, '·') AS "rpad", LTRIM('   x') AS "ltrim", RTRIM('x   ') AS "rtrim", CHR(65) AS "chr", ASCII("examples_book"."title") AS "ord"
#   FROM "examples_book"
#   INNER JOIN "examples_author" ON ("examples_book"."author_id" = "examples_author"."id")
#   WHERE "examples_book"."title" = 'The Hobbit'
#   ORDER BY "examples_book"."id" ASC
#   LIMIT 1

# Result:
#   Lower      -> the hobbit
#   Upper      -> THE HOBBIT
#   Length     -> 10
#   Substr 1,3 -> The
#   Left 3     -> The
#   Right 3    -> bit
#   LPad 18,·  -> ········The Hobbit
#   RPad 18,·  -> The Hobbit········
#   Trim       -> 'spaced'
#   LTrim      -> 'x'
#   RTrim      -> 'x'
#   Replace o0 -> The H0bbit
#   Reverse    -> tibboH ehT
#   StrIndex   -> 5
#   Repeat ab3 -> ababab
#   Chr(65)    -> A
#   Ord(title) -> 84  (codepoint of 'T')
#   MD5        -> 8b843987fd0b2cd3840a09f76addbe41
#   SHA256     -> ff8d72d1b5733b33b1f53251…
#   Concat     -> The Hobbit — J. R. R. Tolkien