Django Creating a model with relationships


Example

Many-to-One Relationship

from django.db import models

class Author(models.Model):
   name = models.CharField(max_length=50)

#Book has a foreignkey (many to one) relationship with author
class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publish_date = models.DateField()

Most generic option. Can be used anywhere you would like to represent a relationship

Many-to-Many Relationship

class Topping(models.Model):
    name = models.CharField(max_length=50)

# One pizza can have many toppings and same topping can be on many pizzas
class Pizza(models.Model):
    name = models.CharField(max_length=50)
    toppings = models.ManyToManyField(Topping)

Internally this is represented via another table. And ManyToManyField should be put on models that will be edited on a form. Eg: Appointment will have a ManyToManyField called Customer, Pizza has Toppings and so on.

Many-to-Many Relationship using Through classes

class Service(models.Model):
     name = models.CharField(max_length=35)

class Client(models.Model):
    name = models.CharField(max_length=35)
    age = models.IntegerField()
    services = models.ManyToManyField(Service, through='Subscription')

class Subscription(models.Model):
     client = models.ForeignKey(Client)
     service = models.ForeignKey(Service)
     subscription_type = models.CharField(max_length=1, choices=SUBSCRIPTION_TYPES)
     created_at = models.DateTimeField(default=timezone.now)

This way, we can actually keep more metadata about a relationship between two entities. As can be seen, a client can be subscribed to several services via several subscription types. The only difference in this case is that to add new instances to the M2M relation, one cannot use the shortcut method pizza.toppings.add(topping), instead, a new object of the through class should be created, Subscription.objects.create(client=client, service=service, subscription_type='p')

In other languages through tables are also known as a JoinColumn , Intersection table or mapping table

One-to-One Relationship

class Employee(models.Model):
   name = models.CharField(max_length=50)
   age = models.IntegerField()
   spouse = models.OneToOneField(Spouse)

class Spouse(models.Model):
   name = models.CharField(max_length=50)

Use these fields when you will only ever have a composition relationship between the two models.