You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/advanced/self-referential.md
+9-5Lines changed: 9 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Self-referential relationships
2
2
3
-
Oftentimes we need to model a relationship between one entity of some class and another entity (or multiple entities) of that **same** class. This is called a **self-referential** or **recursive** relationship. (The pattern is also sometimes referred to as an **adjacency list**.)
3
+
Oftentimes we need to model a relationship between one entity of some class and another entity (or multiple entities) of that **same** class. This is known as a **self-referential** or **recursive** relationship, sometimes also called an **adjacency list**.
4
4
5
5
In database terms this means having a table with a foreign key reference to the primary key in the same table.
6
6
@@ -22,9 +22,13 @@ Using the `sa_relationship_kwargs` parameter, we pass the keyword-argument `remo
22
22
23
23
/// info
24
24
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."_
25
+
The `remote_side` parameter accepts a Python-evaluable string when using Declarative. This allows us to reference `Villain.id` even though the class is still being defined.
26
26
27
-
This allows us to pass the `id` field of the class we are just now defining as the remote side of that relationship.
@@ -34,9 +38,9 @@ Notice that we explicitly defined the relationship attributes we wanted for refe
34
38
35
39
For our purposes, it is necessary that we also provide the `back_populates` parameter to both relationships as explained in detail in a [dedicated chapter](../tutorial/relationship-attributes/back-populates.md){.internal-link target=_blank}.
36
40
37
-
In addition, the type annotations were made by enclosing our `Villain` class name in quotes, since we are referencing a class that is not yet fully defined by the time the interpreter reaches those lines. (See the chapter on [type annotation strings](../tutorial/relationship-attributes/type-annotation-strings.md){.internal-link target=_blank} for a detailed explanation.)
41
+
In addition, the type annotations were made by enclosing our `Villain` class name in quotes, since we are referencing a class that is not yet fully defined by the time the interpreter reaches those lines. See the chapter on [type annotation strings](../tutorial/relationship-attributes/type-annotation-strings.md){.internal-link target=_blank} for a detailed explanation.
38
42
39
-
Finally, as with regular (i.e. non-self-referential) foreign key relationships, it is up to us to decide, whether it makes sense to allow the field to be **empty** or not. In our example, not every villain must have a boss. (In fact, we would otherwise introduce a circular reference chain, which would not make sense in this context.) Therefore we declare `boss_id: Optional[int]` and `boss: Optional['Villain']`. This is analogous to the `Hero`→`Team` relationship we saw [in an earlier chapter](../tutorial/relationship-attributes/define-relationships-attributes.md#optional-relationship-attributes){.internal-link target=_blank}.
43
+
Finally, as with regular (i.e. non-self-referential) foreign key relationships, it is up to us to decide, whether it makes sense to allow the field to be **empty** or not. In our example, not every villain must have a boss (in fact, we would otherwise introduce a circular reference chain, which would not make sense in this context). Therefore we declare `boss_id: Optional[int]` and `boss: Optional['Villain']`. This is analogous to the `Hero`→`Team` relationship we saw [in an earlier chapter](../tutorial/relationship-attributes/define-relationships-attributes.md#optional-relationship-attributes){.internal-link target=_blank}.
0 commit comments