A cheat sheet for Django ORM relationships — version 2.1
I want to start this story with saying thanks to Mahmoud Zalt, who published a really useful article “Eloquent Relationships Cheat Sheet” about a year ago and also gave me permission to use the same structure/images/examples in my article.
In this demo we have 2 models (Owner and Car), and 2 tables (owners and cars).
The Owner can own one Car.The Car can be owned by one Owner.
The Cars table should store the Owner ID.
class Owner(models.Model):
#...
name = models.CharField(max\_length=255)
class Car(models.Model):
#...
name = models.CharField(max\_length=255)
owner = models.OneToOneField(
Owner,
on\_delete=models.CASCADE,
related\_name='car'
)
car = Car.objects.get(id=1)owner = Owner.objects.get(id=1)
# Create relation between Owner and Car.
owner.car = carowner.car.save()
# Create relation between Car and Owner.
car.owner = ownercar.save()
# Get Owner Car
owner.car
# Get Car Owner
car.owner;
In this demo we have 2 models (Thief and Car), and 2 tables (thieves and cars).
The Thief can steal many Cars.The Car can be stolen by one Thief.
The Cars table should store the Thief ID.
class Thief(models.Model):
# ...
name = models.CharField(max\_length=255)
class Car(models.Model):
# ...
name = models.CharField(max\_length=255)
thief = models.ForeignKey(
Thief,
on\_delete=models.CASCADE,
related\_name='cars'
)
thief = Thief.objects.get(id=1)car1 = Car.objects.get(id=1)...
# Create relation between Thief and Car.
thief.cars.add(car1,car2, car3)
# Create relation between Car and Thief.
car.thief = thiefcar.save()
# When we creating new car :car = Car(name = 'test name', thief=thief)car.save()
# Get Thief Car
thief.cars.all()
# Get Car Thief
car.thief
In this demo we have 2 models (Driver and Car), and 3 tables (drivers, cars and a pivot table named car_drivers).
The Driver can drive many Cars.The Car can be driven by many Drivers.
The Pivot table “car_driver” should store the Driver ID and the Car ID.
class Driver(models.Model):
# ...
name = models.CharField(max\_length=255)
class Car(models.Model):
# ...
name = models.CharField(max\_length=255)
drivers = models.ManyToManyField(
Driver,
related\_name='cars'
)
# Create relation between Driver and Car.
driver = Driver.objects.get(id=1)car1 = Car.objects.get(id=1)car2 = Car.objects.get(id=2)
driver.cars.add(car1,car2)
# Create relation between Car and Driver.car = Car.objects.get(id=1)driver1 = Driver.objects.get(id=2)driver2 = Driver.objects.get(id=3)
car.drivers.add(driver1, driver2)
# Get Driver Car
driver.cars.all()
# Get Car Drivers
car.drivers.all()
With Django’s Generic Relations
In this demo we have 3 models (Man, Woman and Car), and 3 tables (men, women and cars).
The Man (buyer) can buy many Cars. The Woman (buyer) can buy many Cars.The Car can be bought by one buyer (Man or Woman).
The Car table should store the Buyer ID and the Buyer table should store the relation between ID and Type.
from django.contrib.contenttypes.fields import GenericForeignKeyfrom django.contrib.contenttypes.fields import GenericRelationfrom django.contrib.contenttypes.models import ContentType
class Car(models.Model):
# ...
name = models.CharField(max\_length=255)
content\_type = models.ForeignKey(ContentType, on\_delete=models.CASCADE)
object\_id = models.PositiveIntegerField()
content\_object = GenericForeignKey()
class Woman(models.Model):
# ...
name = models.CharField(max\_length=255)
cars = GenericRelation(Car)
class Man(models.Model):
# ...
name = models.CharField(max\_length=255)
cars = GenericRelation(Car)
man = Man.objects.get(id=1)woman = Woman.objects.get(id=1)
# Create relation between buyer (Man/Woman) and Car.
car = Car.objects.get(id=1)woman.cars.add(car)
# Create relation between Car and buyer (Men/Women).
man = Man.objects.get(id=1)woman = Woman.objects.get(id=1)
c = Car(name = 'test name',content_object=man)c.save()
c = Car(name = 'test name',content_object=woman)c.save()
# Get buyer (Man/Woman) Cars
man.cars.all()woman.cars.all()
# Get Car buyer (Man and Woman)
car.content_object
With package — django-polymorphic.
In this demo we have 4 models (Buyer, Man, Woman and Car), and 4 tables (buyer, men, women and cars).
The Man (buyer) can buy many Cars. The Woman (buyer) can buy many Cars.The Car can be bought by one buyer (Man or Woman).
The Car table should store the Buyer ID and the Buyer table should store the relation between ID and Type.
from polymorphic.models import PolymorphicModel
class Buyer(PolymorphicModel):_pass
class_ Woman(Buyer):
# ...
name = models.CharField(max\_length=255)
class Man(Buyer):
# ...
name = models.CharField(max\_length=255)
class Car(models.Model):
# Fields
name = models.CharField(max\_length=255)
buyer = models.ForeignKey(
Buyer,
on\_delete=models.CASCADE,
related\_name='cars'
)
man = Buyer.objects.get(id=1) # or Man.objecets.get(id=1)woman = Buyer.objects.get(id=2) # or Woman.objecets.get(id=2)
# Create relation between buyer (Man/Woman) and Car.
man.cars.add(car1, car2)
woman.cars.add(car1, car2)
# Create relation between Car and buyer (Men/Women).
c = Car(name = 'test name', buyer = man)c.save()
c = Car(name = 'test name', buyer = woman)c.save()
# Get buyer (Man/Woman) Cars
man.cars.all()woman.cars.all()
# Get Car buyer (Man and Woman)
car.buyer
With package — django-polymorphic.
In this demo we have 3 models (Valet, Owner and Car), and 4 tables (valets, owners, cars and drivers).
The Valet (driver) can drive many Cars. The Owner (driver) can drive many Cars.The Car can be driven by many drivers (Valet or/and Owner).
The Pivot table “drivers” should store the Driver ID, Driver Type and the CarID.“driver” is a name given to a group of models (Valet and Owner). And it’s not limited to two. The driver type is the real name of the model.
from polymorphic.models import PolymorphicModel
class Driver(PolymorphicModel):pass
class Owner(Driver):
# ...
name = models.CharField(max\_length=255)
class Valet(Driver):
# ...
name = models.CharField(max\_length=255)
class Car(models.Model):
# ...
name = models.CharField(max\_length=255)
drivers = models.ManyToManyField(
Driver,
related\_name='cars'
)
# Create relation between driver (Valet/Owner) and Car.
owner.cars.add(car1, car2)
# Create relation between Car and driver (Valet/Owner).
car.drivers.add(owner, valet)
# Get driver (Valet/Owner) Cars
valet.cars.all()owner.cars.all()
# Get Car drivers (Valet and Owner)
car.drivers.all()car1.drivers.instance_of(Valet)car1.drivers.instance_of(Owner)
I also highly recommend to read the article, that describes polymorphic many to many relationships with another django package (django-gm2m).
Thanks for reading and stay in touch.