JSONField lookups (nested key, contains, has_key)

Django ORM PostgreSQL May 22, 2026 python

JSONField stores jsonb.

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
66
67
68
69
70
# ======================================================================
# `JSONField` stores `jsonb`. Traverse nested keys with `__`
# (`data__specs__format`), test containment with `__contains` (`@>`), and key
# presence with `__has_key` (`?`). GIN indexes accelerate the containment
# lookups.
# ======================================================================

# ----------------------------------------------------------------------
# data.specs.format = 'hardcover'
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(data__specs__format="hardcover")

# SQL:
#   SELECT "examples_book"."id", "examples_book"."title", "examples_book"."author_id", "examples_book"."price", "examples_book"."pages", "examples_book"."published", "examples_book"."is_active", "examples_book"."tags", "examples_book"."data", "examples_book"."search", "examples_book"."title_upper"
#   FROM "examples_book"
#   WHERE ("examples_book"."data" #> '{specs,format}') = '"hardcover"'::jsonb

# Result:
#   Harry Potter
#   The Lord of the Rings

# ----------------------------------------------------------------------
# data.specs.stock = 0
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(data__specs__stock=0)

# SQL:
#   SELECT "examples_book"."id", "examples_book"."title", "examples_book"."author_id", "examples_book"."price", "examples_book"."pages", "examples_book"."published", "examples_book"."is_active", "examples_book"."tags", "examples_book"."data", "examples_book"."search", "examples_book"."title_upper"
#   FROM "examples_book"
#   WHERE ("examples_book"."data" #> '{specs,stock}') = '0'::jsonb

# Result:
#   The Lord of the Rings

# ----------------------------------------------------------------------
# data contains {'specs': {'format': 'ebook'}}
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(data__contains={"specs": {"format": "ebook"}})

# SQL:
#   SELECT "examples_book"."id", "examples_book"."title", "examples_book"."author_id", "examples_book"."price", "examples_book"."pages", "examples_book"."published", "examples_book"."is_active", "examples_book"."tags", "examples_book"."data", "examples_book"."search", "examples_book"."title_upper"
#   FROM "examples_book"
#   WHERE "examples_book"."data" @> '{"specs": {"format": "ebook"}}'::jsonb

# Result:
#   Postgres for Authors

# ----------------------------------------------------------------------
# data has_key 'isbn'
# ----------------------------------------------------------------------

# Django:
Book.objects.filter(data__has_key="isbn")

# SQL:
#   SELECT "examples_book"."id", "examples_book"."title", "examples_book"."author_id", "examples_book"."price", "examples_book"."pages", "examples_book"."published", "examples_book"."is_active", "examples_book"."tags", "examples_book"."data", "examples_book"."search", "examples_book"."title_upper"
#   FROM "examples_book"
#   WHERE "examples_book"."data" ? 'isbn'

# Result:
#   Harry Potter
#   The Hobbit
#   The Lord of the Rings
#   Postgres for Authors