Skip to content

Commit 14c2fc6

Browse files
committed
Added docs
1 parent 1f08c0d commit 14c2fc6

File tree

3 files changed

+86
-5
lines changed

3 files changed

+86
-5
lines changed

docs/advanced/index.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# Advanced User Guide
22

3-
The **Advanced User Guide** is gradually growing, you can already read about some advanced topics.
3+
The **Advanced User Guide** covers advanced topics and features of SQLModel.
44

5-
At some point it will include:
5+
Current topics include:
66

7-
* How to use `async` and `await` with the async session.
8-
* How to run migrations.
9-
* How to combine **SQLModel** models with SQLAlchemy.
7+
* [Working with Decimal Fields](decimal.md) - How to handle decimal numbers in SQLModel
8+
* [Working with UUID Fields](uuid.md) - How to use UUID fields in your models
9+
* [Storing Pydantic Models in JSONB Columns](pydantic-jsonb.md) - How to store and work with Pydantic models in JSONB columns
10+
11+
Coming soon:
12+
13+
* How to use `async` and `await` with the async session
14+
* How to run migrations
15+
* How to combine **SQLModel** models with SQLAlchemy
1016
* ...and more. 🤓

docs/advanced/pydantic-jsonb.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Storing Pydantic Models in JSONB Columns
2+
3+
You can store Pydantic models (and lists or dicts of them) in JSON or JSONB database columns using the `PydanticJSONB` utility.
4+
5+
This is especially useful when:
6+
7+
- You want to persist flexible, nested data structures in your models.
8+
- You prefer to avoid separate relational tables for structured fields like metadata, config, or address.
9+
- You want automatic serialization and deserialization using Pydantic.
10+
11+
## Usage
12+
13+
You can use it with SQLModel like this:
14+
15+
```python
16+
from typing import Optional
17+
from pydantic import BaseModel
18+
from sqlmodel import SQLModel, Field, Column
19+
from sqlmodel.sql.sqltypes import PydanticJSONB
20+
21+
class Address(BaseModel):
22+
street: str
23+
city: str
24+
25+
class User(SQLModel, table=True):
26+
id: Optional[int] = Field(default=None, primary_key=True)
27+
name: str
28+
address: Address = Field(sa_column=Column(PydanticJSONB(Address)))
29+
```
30+
31+
This will store the `address` field as a `JSONB` column in PostgreSQL and automatically serialize/deserialize to and from the `Address` Pydantic model.
32+
33+
If you're using a list or dict of models, `PydanticJSONB` supports that too:
34+
35+
```python
36+
Field(sa_column=Column(PydanticJSONB(List[SomeModel])))
37+
Field(sa_column=Column(PydanticJSONB(Dict[str, SomeModel])))
38+
```
39+
40+
## Requirements
41+
42+
* PostgreSQL (for full `JSONB` support).
43+
* Pydantic v2.
44+
* SQLAlchemy 2.x.
45+
46+
## Limitations
47+
48+
### Nested Model Updates
49+
50+
Currently, updating attributes inside a nested Pydantic model doesn't automatically trigger a database update. This is similar to how plain dictionaries work in SQLAlchemy. For example:
51+
52+
```python
53+
# This won't trigger a database update
54+
row = select(...) # some MyTable row
55+
row.data.x = 1
56+
db.add(row) # no effect, change isn't detected
57+
```
58+
59+
To update nested model attributes, you need to reassign the entire model:
60+
61+
```python
62+
# Workaround: Create a new instance and reassign
63+
updated = ExtraData(**row.data.model_dump())
64+
updated.x = 1
65+
row.data = updated
66+
db.add(row)
67+
```
68+
69+
This limitation will be addressed in a future update using `MutableDict` to enable change tracking for nested fields. The `MutableDict` implementation will emit change events when the contents of the dictionary are altered, including when values are added or removed.
70+
71+
## Notes
72+
73+
* Falls back to `JSON` if `JSONB` is not available.
74+
* Only tested with PostgreSQL at the moment.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ nav:
128128
- advanced/index.md
129129
- advanced/decimal.md
130130
- advanced/uuid.md
131+
- advanced/pydantic-jsonb.md
131132
- Resources:
132133
- resources/index.md
133134
- help.md

0 commit comments

Comments
 (0)