Skip to content

Commit cfa3541

Browse files
committed
Fix formatting and update links
1 parent d0bd01f commit cfa3541

File tree

1 file changed

+17
-79
lines changed

1 file changed

+17
-79
lines changed

docs/advanced/self-referential.md

Lines changed: 17 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,23 @@ Let's do this with **SQLModel**. 🤓
1010

1111
## Using SQLAlchemy arguments
1212

13-
We already learned a lot about [Relationship attributes](../tutorial/relationship-attributes/index.md){.internal-link target=_blank} in previous chapters. We know that **SQLModel** is built on top of **SQLAlchemy** and we know that the latter allows defining self-referential relationships (see [their documentation](https://docs.sqlalchemy.org/en/14/orm/self_referential.html){.external-link target=_blank}).
13+
We already learned a lot about [Relationship attributes](../tutorial/relationship-attributes/index.md){.internal-link target=_blank} in previous chapters. We know that **SQLModel** is built on top of **SQLAlchemy** and we know that the latter allows defining self-referential relationships (see [their documentation](https://docs.sqlalchemy.org/en/20/orm/self_referential.html){.external-link target=_blank}).
1414

15-
To allow more fine-grained control over it, the `Relationship` constructor allows explicitly passing additional keyword-arguments to the [`sqlalchemy.orm.relationship`](https://docs.sqlalchemy.org/en/14/orm/relationship_api.html#sqlalchemy.orm.relationship){.external-link target=_blank} constructor that is being called under the hood via the `sa_relationship_kwargs` parameter. This is supposed to be a mapping (e.g. a dictionary) of strings representing the SQLAlchemy **parameter names** to the **values** we want to pass through as arguments.
15+
To allow more fine-grained control over it, the `Relationship` constructor allows explicitly passing additional keyword-arguments to the [`sqlalchemy.orm.relationship`](https://docs.sqlalchemy.org/en/20/orm/relationship_api.html#sqlalchemy.orm.relationship){.external-link target=_blank} constructor that is being called under the hood via the `sa_relationship_kwargs` parameter. This is supposed to be a mapping (e.g. a dictionary) of strings representing the SQLAlchemy **parameter names** to the **values** we want to pass through as arguments.
1616

17-
Since SQLAlchemy relationships provide the [`remote_side`](https://docs.sqlalchemy.org/en/14/orm/relationship_api.html#sqlalchemy.orm.relationship.params.remote_side){.external-link target=_blank} parameter for just such an occasion, we can leverage that directly to construct the self-referential pattern with minimal code.
17+
Since SQLAlchemy relationships provide the [`remote_side`](https://docs.sqlalchemy.org/en/20/orm/relationship_api.html#sqlalchemy.orm.relationship.params.remote_side){.external-link target=_blank} parameter for just such an occasion, we can leverage that directly to construct the self-referential pattern with minimal code.
1818

19-
```Python hl_lines="12"
20-
# Code above omitted 👆
19+
{* ./docs_src/advanced/self_referential/tutorial001.py ln[6:17] hl[16] *}
2120

22-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:6-17]!}
23-
24-
# Code below omitted 👇
25-
```
26-
27-
<details>
28-
<summary>👀 Full file preview</summary>
29-
30-
```Python
31-
{!./docs_src/advanced/self_referential/tutorial001.py!}
32-
```
21+
Using the `sa_relationship_kwargs` parameter, we pass the keyword-argument `remote_side='Villain.id'` to the underlying relationship property.
3322

34-
</details>
23+
/// info
3524

36-
Using the `sa_relationship_kwargs` parameter, we pass the keyword-argument `remote_side='Villain.id'` to the underlying relationship property.
25+
The SQLAlchemy documentation mentions this in passing, but crucially the `remote_side` value _"may be passed as a Python-evaluable string when using Declarative."_
3726

38-
!!! info
39-
The SQLAlchemy documentation mentions this in passing, but crucially the `remote_side` value _"may be passed as a Python-evaluable string when using Declarative."_
27+
This allows us to pass the `id` field of the class we are just now defining as the remote side of that relationship.
4028

41-
This allows us to pass the `id` field of the class we are just now defining as the remote side of that relationship.
29+
///
4230

4331
## Back-populating and self-referencing
4432

@@ -54,70 +42,17 @@ Finally, as with regular (i.e. non-self-referential) foreign key relationships,
5442

5543
Now let us see how we can create villains with a boss:
5644

57-
```Python hl_lines="6-7"
58-
# Code above omitted 👆
59-
60-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:30-49]!}
61-
62-
# Code below omitted 👇
63-
```
64-
65-
<details>
66-
<summary>👀 Full file preview</summary>
67-
68-
```Python
69-
{!./docs_src/advanced/self_referential/tutorial001.py!}
70-
```
71-
72-
</details>
45+
{* ./docs_src/advanced/self_referential/tutorial001.py ln[30:49] hl[34-35] *}
7346

7447
Just as with regular relationships, we can simply pass our boss villain as an argument to the constructor with `boss=thinnus`.
7548

7649
If we only learn that a villain actually had a secret boss after we have already created him, we can just as easily assign him that boss retroactively:
7750

78-
```Python hl_lines="8"
79-
# Code above omitted 👆
80-
81-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:30-31]!}
82-
83-
# Previous code here omitted 👈
84-
85-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:51-55]!}
86-
87-
# Code below omitted 👇
88-
```
89-
90-
<details>
91-
<summary>👀 Full file preview</summary>
92-
93-
```Python
94-
{!./docs_src/advanced/self_referential/tutorial001.py!}
95-
```
96-
97-
</details>
51+
{* ./docs_src/advanced/self_referential/tutorial001.py ln[30:31,51-55] hl[52] *}
9852

9953
And if we want to add minions to a boss after the fact, this is as easy as adding items to a Python list (because that's all it is 🤓):
10054

101-
```Python hl_lines="11"
102-
# Code above omitted 👆
103-
104-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:30-31]!}
105-
106-
# Previous code here omitted 👈
107-
108-
{!./docs_src/advanced/self_referential/tutorial001.py[ln:57-68]!}
109-
110-
# Code below omitted 👇
111-
```
112-
113-
<details>
114-
<summary>👀 Full file preview</summary>
115-
116-
```Python
117-
{!./docs_src/advanced/self_referential/tutorial001.py!}
118-
```
119-
120-
</details>
55+
{* ./docs_src/advanced/self_referential/tutorial001.py ln[30:31,57-68] hl[61] *}
12156

12257
Since our relationships work both ways, we don't even need to add all our `clone_bot_`s to the session individually. Instead we can simply add `ultra_bot` once again and commit the changes. We do need to refresh them all individually though, if we want to get their updated attributes.
12358

@@ -132,5 +67,8 @@ top_boss_minions = clone_bot_3.boss.boss.minions
13267
assert any(minion is ebonite_mew for minion in top_boss_minions) # passes
13368
```
13469

135-
!!! info
136-
Notice that we can in fact check for **identity** using `is` as opposed to `==` here, since we are dealing with those exact same objects, not just objects that hold the same **data**.
70+
/// info
71+
72+
Notice that we can in fact check for **identity** using `is` as opposed to `==` here, since we are dealing with those exact same objects, not just objects that hold the same **data**.
73+
74+
///

0 commit comments

Comments
 (0)