Lesson 37 of 60 – Django Model Relationships
62%

Django Model Relationships

In real-world applications, database tables are often connected to each other. For example, a student can belong to a course, an employee can belong to a department, and an order can contain multiple products.

Django provides relationship fields such as ForeignKey, OneToOneField, and ManyToManyField to represent these connections between models.

Note: Understanding model relationships is essential for building database-driven Django applications.

1. What is a Model Relationship?

A model relationship connects one database model with another model.

For example, a Student can belong to a Course:

Student → Course

Instead of storing all course information repeatedly inside every student record, Django can use a relationship field.

2. Why Use Relationships?

Relationships help organize related data efficiently.

  • Avoid unnecessary duplication of data.
  • Connect related database records.
  • Make querying related data easier.
  • Represent real-world relationships.
  • Keep database structures organized.

3. Main Types of Django Relationships

Django provides three commonly used relationship fields:

  • ForeignKey – many-to-one relationship.
  • OneToOneField – one-to-one relationship.
  • ManyToManyField – many-to-many relationship.

Each relationship type is useful for a different database design.

4. Understanding One-to-Many Relationships

A one-to-many relationship means one object can be related to many other objects.

For example:

One Course
     ↓
Many Students

A course can have many students, while each student belongs to one course. This is commonly implemented using ForeignKey.

5. Understanding One-to-One Relationships

A one-to-one relationship means one object is associated with exactly one object on the other side.

For example:

User
  ↓
One Profile

A user can have one profile, and that profile belongs to one user.

6. Understanding Many-to-Many Relationships

A many-to-many relationship means multiple objects can be related to multiple objects.

For example:

Students ←→ Courses

A student can enroll in multiple courses, and a course can contain multiple students.

7. ForeignKey Relationship

The ForeignKey field is used to create a many-to-one relationship.

class Course(models.Model):

    name = models.CharField(
        max_length=100
    )


class Student(models.Model):

    name = models.CharField(
        max_length=100
    )

    course = models.ForeignKey(
        Course,
        on_delete=models.CASCADE
    )

8. Understanding on_delete

The on_delete argument specifies what should happen to related objects when the referenced object is deleted.

course = models.ForeignKey(
    Course,
    on_delete=models.CASCADE
)

Different deletion behaviors can be selected depending on the application's requirements.

9. CASCADE

With CASCADE, deleting the referenced object can also delete related objects.

course = models.ForeignKey(
    Course,
    on_delete=models.CASCADE
)

For example, deleting a Course can cause related Student records to be deleted according to the relationship configuration.

Important: Use cascade behavior carefully because deleting one object can affect related records.

10. PROTECT

PROTECT prevents deletion of the referenced object when protected related objects exist.

course = models.ForeignKey(
    Course,
    on_delete=models.PROTECT
)

This is useful when related records should prevent the parent object from being deleted.

11. SET_NULL

SET_NULL sets the relationship field to NULL when the referenced object is deleted.

course = models.ForeignKey(
    Course,
    null=True,
    on_delete=models.SET_NULL
)

The field must allow NULL values when using this option.

12. SET_DEFAULT

SET_DEFAULT sets the relationship field to its configured default value when the referenced object is deleted.

course = models.ForeignKey(
    Course,
    default=1,
    on_delete=models.SET_DEFAULT
)

The field must have an appropriate default value.

13. Creating a Course and Student

First create a Course object:

course = Course.objects.create(
    name="Python"
)

Then create a Student associated with that course:

student = Student.objects.create(
    name="Rahul",
    course=course
)

14. Accessing the Related Object

If Student has a ForeignKey named course, you can access the related Course object through the student.

student = Student.objects.get(
    id=1
)

print(student.course.name)

Django follows the relationship and retrieves the related Course object.

15. Reverse ForeignKey Relationship

You can also access students from a Course object using the default reverse relationship.

course = Course.objects.get(
    id=1
)

students = course.student_set.all()

The default reverse manager is based on the related model name.

16. related_name

The related_name option allows you to give the reverse relationship a custom name.

course = models.ForeignKey(
    Course,
    on_delete=models.CASCADE,
    related_name="students"
)

Now you can access students using:

course.students.all()

17. Querying Through a Relationship

Django allows you to filter records using fields from related models.

students = Student.objects.filter(
    course__name="Python"
)

The double underscore connects the Student field to the Course field.

18. OneToOneField

OneToOneField creates a one-to-one relationship between two models.

class Profile(models.Model):

    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE
    )

    phone = models.CharField(
        max_length=20
    )

Each User can have one related Profile.

19. Accessing a One-to-One Relationship

A related profile can be accessed directly from the user.

user = User.objects.get(
    id=1
)

print(user.profile.phone)

The reverse accessor is based on the relationship configuration and model name unless a custom related name is provided.

20. ManyToManyField

ManyToManyField is used when multiple objects can be connected to multiple objects.

class Course(models.Model):

    name = models.CharField(
        max_length=100
    )


class Student(models.Model):

    name = models.CharField(
        max_length=100
    )

    courses = models.ManyToManyField(
        Course
    )

21. Adding Many-to-Many Relationships

After creating a Student and Course, you can connect them using add().

student.courses.add(
    course
)

Multiple courses can be added:

student.courses.add(
    course1,
    course2
)

22. Reading Many-to-Many Records

You can retrieve all courses associated with a student.

courses = student.courses.all()

for course in courses:

    print(course.name)

The result is a QuerySet of related Course objects.

23. Removing Many-to-Many Relationships

The remove() method removes a relationship without deleting the related objects themselves.

student.courses.remove(
    course
)

The Course object still exists; only the connection is removed.

24. Clearing Many-to-Many Relationships

The clear() method removes all many-to-many relationships from an object.

student.courses.clear()

This removes all Course connections for the student without deleting the Course objects.

25. Setting Many-to-Many Relationships

The set() method can replace the current relationships with a new collection.

student.courses.set(
    [course1, course2]
)

The student's course relationships are replaced by the specified courses.

26. select_related()

select_related() can be used with ForeignKey and OneToOne relationships to retrieve related objects efficiently in the same query pattern.

students = Student.objects.select_related(
    "course"
).all()

This is useful when each student needs its related course information.

27. prefetch_related()

prefetch_related() is useful for efficiently retrieving related objects, including many-to-many and reverse relationships.

students = Student.objects.prefetch_related(
    "courses"
).all()

It helps reduce unnecessary database queries when displaying related data.

28. Choosing the Right Relationship

Relationship Example
ForeignKey Many Students → One Course
OneToOneField One User → One Profile
ManyToManyField Many Students ↔ Many Courses

Choose the relationship based on how the real-world data is connected.

29. Common Relationship Mistakes

  • Choosing the wrong relationship type.
  • Forgetting the required on_delete argument for ForeignKey.
  • Not considering what should happen to related objects when a parent is deleted.
  • Using a ForeignKey when the data actually requires many-to-many connections.
  • Forgetting to run migrations after changing relationship fields.
  • Using incorrect related field names in queries.
  • Not understanding reverse relationships.
  • Fetching related objects inefficiently in large lists.
  • Forgetting to use select_related() or prefetch_related() when appropriate.

30. Summary of Django Relationships

Django relationships allow models to represent connections between database tables.

  • ForeignKey represents a many-to-one relationship.
  • OneToOneField represents a one-to-one relationship.
  • ManyToManyField represents a many-to-many relationship.
  • on_delete controls behavior when referenced objects are deleted.
  • related_name can customize reverse relationship access.
  • Double underscores can be used to query related fields.
  • add(), remove(), clear(), and set() manage many-to-many relationships.
  • select_related() is useful for ForeignKey and OneToOne relationships.
  • prefetch_related() is useful for many-to-many and reverse relationships.
  • Relationships should be designed according to the real-world data structure.

📌 Key Points

  • Django supports three main relationship types.
  • ForeignKey is used for many-to-one relationships.
  • OneToOneField is used for one-to-one relationships.
  • ManyToManyField is used for many-to-many relationships.
  • on_delete defines behavior when related objects are deleted.
  • related_name provides a custom reverse relationship name.
  • Related fields can be queried using double-underscore notation.
  • select_related() can optimize ForeignKey and OneToOne queries.
  • prefetch_related() can optimize many-to-many and reverse relationships.

🧠 Quick Quiz

Question: Which Django field is commonly used to create a many-to-one relationship?