In our previous  Django Tutorial, we have discussed on Django models. Now we are going to discuss about Creating Relationships in Django Models. We are going to cover up the following topics.

1  Relationships in Django models
  • One To One (OneToOneField)
  • Many To Many (ManyToManyField)
  • One To Many (ForeignKey)
2  Data integrity options

Relationships in Django models

Django uses ORM (a library/tool)  that creates a bridge between Relational Database Tables and Python  Objects. It allows us to write Python code instead of SQL queries to run CRUD (Create, Read, Update and Delete) operations by providing a high-level abstraction upon a relational database.

As Developers designed Django models with the use of an ORM (Object-Relational-Mapper), thus It also supports relationships amongst one another. It is also used to associate records on the basis of a key or id. Which has improved data maintenance, query performance and less data redundancy, and so on.

Django models also support the three relationships that Relational Database Systems supports. They are…

  1. One To One (OneToOneField)
  2. Many To Many (ManyToManyField)
  3. One To Many (ForeignKey)

One-To-Many Relationship in Django models.

In a One-To-Many relationship one record (object) of a model can have relationship with many other records of another model. To define a One-To-Many relationship in Django models the ‘ForeignKey’ field. Suppose, A person object of “Person” model can has one or many Cars. So, It will be a One-To-Many relationship.

from django.db import models
class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

    def __str__(self):
        return f'{self.first_name} {self.last_name}'    

class Car(models.Model):
    owner = models.ForeignKey(Person,on_delete=models.SET_NULL,null=True)
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

The use of One-To-Many Relationship improves data maintenance and gives database level benefits providing an API (Application Programmable Interface) to access related data. First make some objects of Car model in the database.

Queries to access data of related tables:

# Get the Owners first_name of a given Car 
owner_of_a_specific_car = Car.objects.get(name = 'BMW'  ).owner.first_name

# Get Item cars that belong to the owner 'Zaira'
owners_all_cars = Car.objects.filter(owner__first_name ='Zaira')

Many To Many relationships in Django models

In a Many-To-Many relationship one record (object) of a model (table in database) can have relationship with many other records of another model(table in database) and vice versa. That means, each object of one model can be related with more than one object of another model.

For example:

A person can have multiple cars and the same model of car can be owned by many people. So, it would be more suitable  to use Many-To-Many relationship rather than One-To-Many (ForeignKey). So let’s alter our model.

class Car(models.Model):
    owner = models.ManyToManyField(Person,blank=True)
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

The ‘Person’ model  has the ‘first_name’ and ‘last_name’ fields and Car  model has the owner field related with the ‘Person’ model. [owner = models.ManyToManyField(Person,blank=True)] The models.ManyToManyField() creates the many to many relationship via a “junction table”(also known as intermediary table), The first argument ‘Person’ indicates the relationship model and the optional blank=True argument allows a Car record to be created without the need of an owner value.

Junction Table

Here, Django generates the junction table to hold the relationships between the Person and Car records through their primary keys. For example:

person_idcar_id
11
21
22
Junction Table

Queries to access data of  related tables:

# Get All Owners of a given Car 
car1 = Car.objects.get(name = 'BMW')
owners_of_a_specific_car= car1.owner.all()

#Get all the Cars of a specific Person (One Way)
person1 = Person.objects.get(first_name='Zaira')
cars_of_person1 = person1.car_set.all()

# Get Cars that belong to the owner 'Zaira' (Another Way)
owners_all_cars = Car.objects.filter(owner__first_name='Zaira')

One-To-One Relationships in Django Models

In a one to one relationship one record (object) of a model (table in database) can have relationship with only one record of another model(table in database). For example: Each object of Person model can has only one Profile. So, the relation will be One-To-One.

class PersonsProfile(models.Model):
    person = models.OneToOneField(Person,on_delete=models.CASCADE,primary_key=True)
    bio = models.CharField(max_length=100,null=True,blank=True)
    phone_no = models.PositiveIntegerField(unique=True)

    def __str__(self):
        return self.person.full_name

In OneToOneField the first argument indicates the relationship model and the second argument on_delete = models.CASCADE indicates that if the object of “Person” model is deleted then the object of “PersonProfile” model related with that object will also be deleted. It is a good practice to name the filed related by “OneToOneField” with the same name as that of the related model but in lowercase.

Queries to access data of related tables:

# Get the phone_no of a specific person.  
person1 = Person.objects.get(first_name='Zaira')
persons_phone_no = person1.personsprofile.phone_no

Data integrity options

As we create relationship between models we will have to define the behavior of records when the related records will be deleted. The behavior is added using ‘on_delete’ parameter in the relational field. ‘on_delete’ parameter has several values. They are discussed below:

  • on_delete = models.CASCADE – It will automatically delete all the related records when a  record is deleted. This is set by default.
  • on_delete = models.PROTECT – It prevents a record from deletion having relation with other records.
  • on_delete = models.SET_NULL – It assigns NULL to the relational field when a record is deleted, provided null = True is set.
  • on_delete = models.SET_DEFAULT – It assigns default values to the relational field when you delete a value, you must provide a default value.
  • on_delete = models.SET() – It can either take a default value as parameter, or a callable, the return value of which will be assigned to the field.
  • on_delete = models.DO_NOTHING – It does nothing with the related fields. It’s not encouraged to use because it’s a bad practice.

+ posts

Author | Python-Django Developer

+ posts

Full-stack Developer (Python | Django | React | React-Native | Angular | Vue)