Suppose I two models which have ManyToMany relation with each other. And suppose my models are below"
name = models.CharField(max_length=254)
courses = models.ManyToManyField(Course, required=False)
finished = models.BooleanField(default=False) # THIS KIND OF FUNCTIONALITY I WANT
name = models.CharField(max_length=254)
Now what I explained above might seem a right solution, but look at this example:
john = Student.objects.create(name="John")
eng_course = Course.objects.create(name="English")
math_course = Course.objects.create(name="Mathematics")
cs_course = Course.objects.create(name="Computer Science")
Now lets say
john has finished
eng_course, and I want the
eng_course to be
True. So, if I do below:
john.finished = True
Then this will make
True for all courses, but I just want it to have
So, I hope I tried my best to explain the problem. So, can anyone help me in implementing the functionality/behavior I am desiring?
For what you issued it looks like you want to specify custom attributes on a Many to Many relationship.
@leandrodesouzadev I read the link that you shared but I did not understand it. Can you provide me an example on the code that I shared in my question? Also let’s say we have intermediary Model
Finished, how would I access the intermediary Model’s attributes?
Like if I want to see the
finished status of
eng_course, should I do it like this:
john_eng_course_finished = Finished.objects.create(student=john, course=eng_course, finished=False)
or if I want to update the same, then should I do it like this:
john.courses.filter(name="English").finished = True
Kindly clear up all the things I stated above and if possible please explain me providing the example using the Models I wrote in my question.
When you have a
Student and a
Enroll on that course.
You can add a
Enrollment table that would look like
student = models.ForeignKey("Student", on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
finished = models.BooleanField(default=False)
# other infos
enrollments = models.ManyToManyField(Course, through=Enrollment)
Then you can add your enrollments:
Or maybe using the enrollments set on the student.
That’s not necessary. Using the
through attribute still allows all the normal many-to-many operations to be performed. You can still use operations like
john.courses.add(eng_course). When you don’t need to reference the
through table, you can ignore it.
(I would also recommend keeping the name
courses as the reference to
@leandrodesouzadev and @KenWhitesell thank you for explaining. I have one question which is still not answered. And that is how would I access the
finished value for
eng_course? Secondly, also tell me if we have to make the class Diagram or Database Design, then what relationship should be should between the two classes
Course and the other class
Ignore the many-to-many relationship for the moment.
Look at just the Student and Enrollment models.
What you have is a reverse foreign key relationship from Student to Enrollment.
john is your
john.enrollment_set is the related object manager created for that relationship, and
john.enrollment_set.all() is the complete set of all
In this case, since you only want one instance of
Enrollment, you can use get:
john.enrollment_set.get(course=eng_course) (You do want to ensure that in the Enrollment model, the fields
course are defined as unique together.)
In all cases, a many-to-many relationship is modeled using a “join table” connecting two tables. This join table consists of two foreign keys, one to each of the two tables it is joining. This is a standard relational db technique.
The differences between using the
through attribute and not using it is that by using it, you’re making that join table to be an explicit model and not something implicitly created by Django and otherwise hidden from view.
So, depending upon how your instructor would want to see it modelled, you can continue to show this as just a many-to-many relationship between the two with an annotation describing the additional fields.
Or, if you want to show the additional detail of that Enrollment model, the relationship is the same as any other ForeignKey relationship. You have a Many-To-One relationship from Enrollment to both Student and Course. (The “many” side of a many-to-one relationship is always the table with the Foreign Key.)
Thank you @KenWhitesell for explaining in detail.