Lesson 38 of 60 – Django ForeignKey
63%

Django ForeignKey

The ForeignKey field is one of the most commonly used relationship fields in Django. It is used to create a many-to-one relationship between two models.

For example, one course can have many students, while each student can belong to one course.

Note: ForeignKey is useful whenever many records need to refer to one related record.

1. What is ForeignKey?

ForeignKey creates a many-to-one relationship between two Django models.

For example:

Course
   ↓
Many Students

One Course can have many Students, but each Student can point to one Course.

2. Why Use ForeignKey?

ForeignKey allows related database records to be connected without duplicating the complete information.

  • Connect related models.
  • Avoid repeated data.
  • Represent real-world relationships.
  • Make related queries easier.
  • Build structured database applications.

3. Basic ForeignKey Syntax

The basic syntax is:

field_name = models.ForeignKey(
    ModelName,
    on_delete=models.CASCADE
)

The first argument specifies the related model and on_delete specifies what should happen when the related object is deleted.

4. Creating a Course Model

Suppose we have a Course model:

from django.db import models

class Course(models.Model):

    name = models.CharField(
        max_length=100
    )

    fee = models.IntegerField()

This model can store course information.

5. Creating a Student Model

Now we can connect Student with Course using ForeignKey.

class Student(models.Model):

    name = models.CharField(
        max_length=100
    )

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

The course field connects each Student with a Course.

6. Understanding Many-to-One

Suppose a Python course has three students:

Python
 ├── Rahul
 ├── Aman
 └── Priya

There is one Course object and multiple Student objects connected to it. This is a many-to-one relationship.

7. Understanding on_delete

The on_delete argument is required when defining a ForeignKey. It controls what happens to related objects when the referenced object is deleted.

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

8. CASCADE

CASCADE causes related objects to be deleted when the referenced object is deleted.

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

For example, deleting a Course can delete the related Student records under this configuration.

Important: Use CASCADE carefully because deletion can affect related records.

9. 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 a parent record should not be deleted while related records depend on it.

10. SET_NULL

SET_NULL sets the ForeignKey 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 for this behavior.

11. SET_DEFAULT

SET_DEFAULT changes the ForeignKey value to its configured default when the referenced object is deleted.

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

An appropriate default value must be configured.

12. DO_NOTHING

DO_NOTHING tells Django not to perform an automatic action when the referenced object is deleted.

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

The database may still enforce its own constraints, depending on the database configuration.

13. Creating a Course Object

First create a Course object:

course = Course.objects.create(
    name="Python",
    fee=10000
)

The returned object can then be assigned to a Student.

14. Creating a Student with ForeignKey

You can assign the Course object directly to the ForeignKey field.

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

Now the Student is connected to the Python Course.

15. Assigning Using course_id

Django also provides a database-oriented field attribute ending in _id.

student = Student.objects.create(
    name="Aman",
    course_id=1
)

Here, 1 represents the primary key of the Course.

16. Accessing the Related Course

After retrieving a Student, you can access its Course through the ForeignKey field.

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

print(student.course.name)

Django follows the relationship and returns the related Course object.

17. Accessing the ForeignKey ID

You can access the primary key of the related Course using course_id.

print(student.course_id)

This gives the ID stored for the related Course.

18. Reverse Relationship

A ForeignKey also provides a reverse relationship from the referenced model to the related objects.

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

students = course.student_set.all()

By default, Django uses the related model name followed by _set.

19. Using related_name

You can give the reverse relationship a custom name using related_name.

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

Now the reverse relationship can be accessed as:

course.students.all()

20. Filtering Using ForeignKey

Django allows you to filter records using fields from the related model.

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

The double underscore connects the Student's ForeignKey with the Course's name field.

21. Filtering by ForeignKey ID

You can filter students using the related Course ID.

students = Student.objects.filter(
    course_id=1
)

This returns students whose Course has the specified primary key.

22. Using get() with ForeignKey

You can retrieve a related object using get().

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

students = Student.objects.filter(
    course=course
)

This returns students connected to that Course.

23. ForeignKey in Templates

ForeignKey data can easily be displayed in Django templates.

<h3>{{ student.name }}</h3>

<p>
Course: {{ student.course.name }}
</p>

<p>
Fee: {{ student.course.fee }}
</p>

Django follows the relationship using dot notation.

24. ForeignKey in a View

A view can retrieve students and pass them to a template.

from django.shortcuts import render
from .models import Student

def student_list(request):

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

    return render(
        request,
        "students.html",
        {"students": students}
    )

25. select_related() with ForeignKey

select_related() is useful when retrieving objects along with their ForeignKey relationships.

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

It can reduce additional database queries when related Course information is needed for many Student objects.

26. ForeignKey with Forms

Django Model Forms can automatically provide a form field for a ForeignKey.

from django import forms
from .models import Student

class StudentForm(forms.ModelForm):

    class Meta:
        model = Student

        fields = [
            "name",
            "course"
        ]

The form can use available Course objects when selecting a course.

27. ForeignKey and Migrations

After adding or changing a ForeignKey field, migrations should normally be created and applied.

python manage.py makemigrations

python manage.py migrate

Django uses migrations to apply the model changes to the database schema.

28. Complete ForeignKey Example

from django.db import models


class Course(models.Model):

    name = models.CharField(
        max_length=100
    )

    fee = models.IntegerField()

    def __str__(self):
        return self.name


class Student(models.Model):

    name = models.CharField(
        max_length=100
    )

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

    def __str__(self):
        return self.name

In this example, one Course can have many Students.

29. Common ForeignKey Mistakes

  • Forgetting the on_delete argument.
  • Choosing an inappropriate deletion behavior.
  • Forgetting to run migrations after changing the model.
  • Using an incorrect related field name in queries.
  • Confusing course with course_id.
  • Not understanding the reverse relationship.
  • Deleting related objects unintentionally with CASCADE.
  • Making unnecessary database queries when displaying related objects.

30. ForeignKey Summary

ForeignKey is an important Django relationship field used to connect many objects to one related object.

  • It creates a many-to-one relationship.
  • It connects one model with another model.
  • on_delete defines deletion behavior.
  • CASCADE can delete related objects.
  • PROTECT prevents deletion when protected relations exist.
  • SET_NULL can set the relationship to NULL.
  • related_name customizes reverse access.
  • Double underscores are used to query related fields.
  • select_related() can optimize ForeignKey queries.
  • ForeignKey changes should be followed by migrations.

📌 Key Points

  • ForeignKey creates a many-to-one relationship.
  • One Course can have many Students.
  • on_delete controls what happens when a referenced object is deleted.
  • related_name provides a custom reverse relationship name.
  • course gives access to the related Course object.
  • course_id gives the related Course primary key.
  • Related fields can be queried using double-underscore syntax.
  • select_related() is useful for efficiently loading ForeignKey relationships.
  • Use migrations after changing ForeignKey definitions.

🧠 Quick Quiz

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