# Create Models with a Many-to-Many Link We'll now support **many-to-many** relationships using a **link table** like this: many-to-many table relationships Let's start by defining the class models, including the **link table** model. ## Link Table Model As we want to support a **many-to-many** relationship, now we need a **link table** to connect them. We can create it just as any other **SQLModel**: ```Python hl_lines="6-12" {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:1-12]!} # Code below omitted 👇 ```
👀 Full file preview ```Python {!./docs_src/tutorial/many_to_many/tutorial001.py!} ```
This is a **SQLModel** class model table like any other. It has two fields, `team_id` and `hero_id`. They are both **foreign keys** to their respective tables. We'll create those models in a second, but you already know how that works. And **both fields are primary keys**. We hadn't used this before. 🤓 ## Team Model Let's see the `Team` model, it's almost identical as before, but with a little change: ```Python hl_lines="8" # Code above ommited 👆 {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:15-20]!} # Code below omitted 👇 ```
👀 Full file preview ```Python {!./docs_src/tutorial/many_to_many/tutorial001.py!} ```
The **relationship attribute `heroes`** is still a list of heroes, annotatted as `List["Hero"]`. Again, we use `"Hero"` in quotes because we haven't declared that class yet by this point in the code (but as you know, editors and **SQLModel** understand that). We use the same **`Relationship()`** function. We use **`back_populates="teams"`**. Before we referenced an attribute `team`, but as now we can have many, we'll rename it to `teams` when creating the `Hero` model. And here's the important part to allow the **many-to-many** relationship, we use **`link_model=HeroTeamLink`**. That's it. ✨ ## Hero Model Let's see the other side, here's the `Hero` model: ```Python hl_lines="9" # Code above ommited 👆 {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:23-29]!} # Code below omitted 👇 ```
👀 Full file preview ```Python {!./docs_src/tutorial/many_to_many/tutorial001.py!} ```
We **removed** the previous `team_id` field (column) because now the relationship is done via the link table. 🔥 The relationship attribute is now named **`teams`** instead of `team`, as now we support multiple teams. It is no longer an `Optional[Team]` but a list of teams, annotated as **`List[Team]`**. We are using the **`Relationship()`** here too. We still have **`back_populates="heroes"`** as before. And now we have a **`link_model=HeroTeamLink`**. ✨ ## Create the Tables The same as before, we will have the rest of the code to create the **engine**, and a function to create all the tables `create_db_and_tables()`. ```Python hl_lines="9" # Code above ommited 👆 {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:32-39]!} # Code below omitted 👇 ```
👀 Full file preview ```Python {!./docs_src/tutorial/many_to_many/tutorial001.py!} ```
And as in previous examples, we will add that function to a function `main()`, and we will call that `main()` function in the main block: ```Python hl_lines="4" # Code above ommited 👆 {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:78-79]!} # We will do more stuff here later 👈 {!./docs_src/tutorial/many_to_many/tutorial001.py[ln:83-84]!} ```
👀 Full file preview ```Python {!./docs_src/tutorial/many_to_many/tutorial001.py!} ```
## Run the Code If you run the code in the command line, it would output:
```console $ python app.py // Boilerplate ommited 😉 INFO Engine CREATE TABLE team ( id INTEGER, name VARCHAR NOT NULL, headquarters VARCHAR NOT NULL, PRIMARY KEY (id) ) INFO Engine [no key 0.00033s] () INFO Engine CREATE TABLE hero ( id INTEGER, name VARCHAR NOT NULL, secret_name VARCHAR NOT NULL, age INTEGER, PRIMARY KEY (id) ) INFO Engine [no key 0.00016s] () INFO Engine // Our shinny new link table ✨ CREATE TABLE heroteamlink ( team_id INTEGER, hero_id INTEGER, PRIMARY KEY (team_id, hero_id), FOREIGN KEY(team_id) REFERENCES team (id), FOREIGN KEY(hero_id) REFERENCES hero (id) ) INFO Engine [no key 0.00031s] () INFO Engine COMMIT ```
## Recap We can support **many-to-many** relationships between tables by declaring a link table. We can create it the same way as with other **SQLModel** classes, and then use it in the `link_model` parameter to `Relationship()`. Now let's work with data using these models in the next chapters. 🤓