sqlmodel/docs/tutorial/relationship-attributes/define-relationships-attributes.md
Jorge Alvarado 0aaf39d539
✏ Fix typo in docs/tutorial/relationship-attributes/define-relationships-attributes.md (#239)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-27 23:31:38 +02:00

4.1 KiB
Raw Blame History

Define Relationships Attributes

Now we are finally in one of the most exciting parts of SQLModel.

Relationship Attributes.

We currently have a team table:

idnameheadquarters
1PreventersSharp Tower
2Z-ForceSister Margarets Bar

And a hero table:

idnamesecret_nameageteam_id
1DeadpondDive Wilsonnull2
2Rusty-ManTommy Sharp481
3Spider-BoyPedro Parqueadornull1

Now that you know how these tables work underneath and how the model classes represent them, it's time to add a little convenience that will make many operations in code simpler.

Declare Relationship Attributes

Up to now, we have only used the team_id column to connect the tables when querying with select():

{!./docs_src/tutorial/connect/insert/tutorial001.py[ln:1-18]!}

# Code below omitted 👇
👀 Full file preview
{!./docs_src/tutorial/connect/insert/tutorial001.py!}

This is a plain field like all the others, all representing a column in the table.

But now let's add a couple of new special attributes to these model classes, let's add Relationship attributes.

First, import Relationship from sqlmodel:

{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:1-3]!}

# Code below omitted 👇
👀 Full file preview
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}

Next, use that Relationship to declare a new attribute in the model classes:

{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py[ln:1-21]!}

# Code below omitted 👇
👀 Full file preview
{!./docs_src/tutorial/relationship_attributes/define_relationship_attributes/tutorial001.py!}

What Are These Relationship Attributes

These new attributes are not the same as fields, they don't represent a column directly in the database, and their value is not a singular value like an integer. Their value is the actual entire object that is related.

So, in the case of a Hero instance, if you call hero.team, you will get the entire Team instance object that this hero belongs to.

For example, you could check if a hero belongs to any team (if .team is not None) and then print the team's name:

if hero.team:
    print(hero.team.name)

Optional Relationship Attributes

Notice that in the Hero class, the type annotation for team is Optional[Team].

This means that this attribute could be None, or it could be a full Team object.

This is because the related team_id could also be None (or NULL in the database).

If it was required for a Hero instance to belong to a Team, then the team_id would be int instead of Optional[int].

And the team attribute would be a Team instead of Optional[Team].

Relationship Attributes With Lists

And in the Team class, the heroes attribute is annotated as a list of Hero objects, because that's what it will have.

SQLModel (actually SQLAlchemy) is smart enough to know that the relationship is established by the team_id, as that's the foreign key that points from the hero table to the team table, so we don't have to specify that explicitly here.

!!! tip There's a couple of things we'll check again in some of the next chapters, about the List["Hero"] and the back_populates.

But for now, let's first see how to use these relationship attributes.

Next Steps

Now let's see some real examples of how to use these new relationship attributes in the next chapters.