Relationships between people are complicated; what about between models?
It can seem easy in theory… up to the point when you have to develop your first real app which needs to set up relationships (also know as associations) between models.
As usual, my explanation is going to involve cats. Lots of them. So brace yourself.
This post assumes understanding of Django models. If you don’t know much about them, read the other post of mine.
One cat, one owner
Imagine this: Mike has a cat named Luna.
Mike has only one cat, Luna, and Luna has only one owner, Mike. Such relationships are called one-to-one.
How can we implement it in code?
In database it will look like this:
Luna has the same
id as their owner (and no
id of its own)
Here’s how you would create a cat for a person:
owner = ... cat = Cat(owner = owner, name = 'Luna') cat.save()
And here’s how you would get the cat for the person:
owner = ... owner.cat
And the owner of the cat:
cat = ... cat.owner
Other examples of one-to-one:
- a user has only one profile;
- a country has only one capital.
Many cats, one owner
Let’s look another example. People can have a lot of cats.
Eva has three cats: Luna, Jasper, and Max. The relationship between Eva and their cats is called many-to-one or one-to-many.
And in database:
You can now create as many cats for a particular person as you want:
owner = ... owner.cat_set.create(name = 'Luna') owner.cat_set.create(name = 'Jasper') owner.cat_set.create(name = 'Max')
To get all the cats for a person, you’d do:
owner = ... owner.cat_set.all() # gives us a list of cat objects: # [<Cat Luna>, <Cat Jasper>, <Cat Max>]
And to get the owner of a particular cat:
cat = ... cat.owner
Other examples of many-to-one:
- a user can upload many pictures;
- a person can have multiple bank accounts;
- a product listing can have several reviews;
- an author can have several articles.
Many cats, many owners
Earth has finally embraced polyamory and shit.
So now one cat has many owners and one owner has many cats. Here we have three owners: Eva, Alex and Mike. Eva has Max and Luna; Alex – Max, Luna, and Jasper; Mike – Tigger and Max. You can notice that Max has three owners: Eva, Alex, and Mike.
Pay attention to extra orange table which will be created automatically. This extra table creates relationships between models.
So how do we create such polyamory relationships?
First of all we should create cats and owners like this:
owner = Owner(name = 'Eva') owner.save() ... cat = Cat(name = 'Max') cat.save() ...
The immoral polyamory emerges:
And here’s how we can inspect this relationship by listing all owners of a cat, or all cats of a particular owner:
owner.cats.all() # [cat] cat.owners.all() # [owner]
Other examples of many-to-many:
- a virtual basket can contain many products, and a product can be in multiple baskets;
- a person can have accounts at many banks, and a bank can have many clients;
- a book can be written by many authors, and an author can write many books;