The ManyToManyField is used when multiple objects from one model
can be related to multiple objects from another model.
For example, a student can enroll in multiple courses, and each course can have multiple students.
ManyToManyField creates a many-to-many relationship between two
Django models.
For example:
Students ←→ Courses
A student can select many courses, and a course can contain many students.
ManyToManyField is useful when both sides of a relationship can contain multiple related records.
The basic syntax is:
field_name = models.ManyToManyField(
ModelName
)
The field is normally defined on one of the models participating in the relationship.
Suppose we have a Course model:
from django.db import models
class Course(models.Model):
name = models.CharField(
max_length=100
)
fee = models.IntegerField()
def __str__(self):
return self.name
This model stores course information.
Now we can connect Student with Course using ManyToManyField.
class Student(models.Model):
name = models.CharField(
max_length=100
)
courses = models.ManyToManyField(
Course
)
A Student can now be connected with multiple Course objects.
Suppose three students are enrolled in different courses:
Rahul → Python, SQL
Aman → Java, Python
Priya → SQL, Java
At the same time, Python can have Rahul and Aman, while SQL can have Rahul and Priya.
Django automatically manages an intermediate database table for a ManyToManyField.
Student
↓
Intermediate Relationship Table
↓
Course
You normally do not need to manually create this table when using the standard ManyToManyField configuration.
First create a Student object:
student = Student.objects.create(
name="Rahul"
)
The student can now be connected to one or more courses.
python = Course.objects.create(
name="Python",
fee=10000
)
sql = Course.objects.create(
name="SQL",
fee=7000
)
Now we have two Course objects that can be assigned to the Student.
Use the add() method to connect a Course to a Student.
student.courses.add(
python
)
The Student is now connected to the Python course.
Multiple courses can be added at the same time.
student.courses.add(
python,
sql
)
The student is now connected to both Python and SQL.
Use all() to retrieve all courses associated with a student.
courses = student.courses.all()
for course in courses:
print(course.name)
The result is a QuerySet containing related Course objects.
The exists() method can be used to check whether related records
exist.
if student.courses.exists():
print("Courses found")
This is useful when you only need to know whether at least one related record exists.
Use count() to find how many courses are associated with a
student.
total = student.courses.count()
print(total)
This returns the number of related Course records.
The remove() method removes a relationship between two objects.
student.courses.remove(
python
)
The Python Course itself is not deleted. Only the relationship is removed.
The clear() method removes all Course relationships from a
Student.
student.courses.clear()
The Course records remain in the database. Only the many-to-many connections are removed.
The set() method replaces the current related objects with a new
collection.
student.courses.set(
[python, sql]
)
The student's existing Course relationships are replaced by the specified courses.
Django creates and manages the intermediate relationship table automatically for a normal ManyToManyField.
class Student(models.Model):
name = models.CharField(
max_length=100
)
courses = models.ManyToManyField(
Course
)
You can work with the relationship through the Django ORM without manually managing the intermediate table.
The related_name option can customize the reverse relationship.
courses = models.ManyToManyField(
Course,
related_name="students"
)
Now a Course can access its related students using:
course.students.all()
If no related_name is specified, Django creates a default
reverse relationship based on the model and field configuration.
With related_name="students", you can write:
students = course.students.all()
for student in students:
print(student.name)
This allows you to move from Course back to Student.
Django allows you to filter Students using fields from related Courses.
students = Student.objects.filter(
courses__name="Python"
)
The double underscore is used to traverse the many-to-many relationship.
You can also find Courses associated with a particular Student.
courses = Course.objects.filter(
students__name="Rahul"
)
This works when the reverse relationship is named
students.
Related courses can be displayed in a Django template using a loop.
<h3>{{ student.name }}</h3>
<ul>
{% for course in student.courses.all %}
<li>
{{ course.name }}
</li>
{% endfor %}
</ul>
The template can access all related Course objects.
A view can retrieve a Student and pass it to a template.
from django.shortcuts import render
from .models import Student
def student_detail(request, id):
student = Student.objects.get(
id=id
)
return render(
request,
"student_detail.html",
{"student": student}
)
The template can then display the student's courses.
prefetch_related() can efficiently retrieve many-to-many
relationships.
students = Student.objects.prefetch_related(
"courses"
).all()
This can reduce unnecessary database queries when displaying many students and their related courses.
A ModelForm can include a ManyToManyField.
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = [
"name",
"courses"
]
Django can provide a form control for selecting multiple related courses.
Sometimes the relationship itself needs additional information.
In that situation, Django allows you to define a custom intermediate model
using through.
class Enrollment(models.Model):
student = models.ForeignKey(
Student,
on_delete=models.CASCADE
)
course = models.ForeignKey(
Course,
on_delete=models.CASCADE
)
enrolled_date = models.DateField()
A custom intermediate model is useful when the relationship needs fields such as enrollment date, status, marks, or other information.
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
)
courses = models.ManyToManyField(
Course,
related_name="students"
)
def __str__(self):
return self.name
Now one Student can have many Courses, and one Course can have many Students.
add(), set(), or similar relationship methods.prefetch_related() when loading many related records.ManyToManyField is used when multiple objects can be connected to multiple objects.
add() adds relationships.remove() removes selected relationships.clear() removes all relationships.set() replaces the current relationships.related_name customizes reverse access.prefetch_related() can optimize many-to-many queries.ManyToManyField creates a many-to-many relationship.add() to create relationships.remove() to remove selected relationships.clear() to remove all relationships.set() to replace relationships.related_name provides convenient reverse access.prefetch_related() can improve related-object loading.Question: Which Django field is used to create a many-to-many relationship?