DEV Community

Cover image for Models' Relationship In Django
Manar Imad
Manar Imad

Posted on

Models' Relationship In Django

Hello BackEnders

Today, I decided to explain OneToOne , ManyToMany , and Foreignkey in Django

Django model
So let's get started:

Why do we use relationships?

The first step to understand the relationships is to understand why we need them. Let's not talk too much about the concept of "Normalization", imagine if we have a table with students names, gender, and school events :

StudentID StudentName StudentGender StudentsClass StudentDesk SchoolEvents
1 Natchos Male 4A 321 Zoo Visit, Charity Day
2 Manar Female 5A 40 Charity Day
3 Kareem Male 4A 66 Zoo Visits , Math Competition

you can notice here that every student has a desk "represented with a number" but why do we have this data in this table? Also, "Male" in StudentGender and "4A" in StudentsClass has been repeated twice in the table. And the worst is in the SchoolEvents column. Just think if we want to delete the Zoo Visit from Natchos's ongoing events, the Charity Day will be deleted too!
Imagine if we have 100 or 1000 students!

Instead, we have to divide the table into smaller tables "four tables in our case"

StudentID StudentName
1 Natchos
2 Manar
3 Kareem
ID StudentGender
1 Male
2 Female
ID StudentsClass
1 4A
2 5A
ID Events
1 Zoo Visit
2 Charity Day
3 Math Competition

Perfect. But what is next? We need a way "a link" to tell the database that this particular student is in this class, has this gender and will go to these events.
That is what we do with relationships. A relationship is an association between two entities.

Foreignkey:

I started with Foreignkey because it is the easiest to understand.

Foreignkey in Django represents "one to many" also called "many to one" relationship in the database.
it is just the same as its name one to many! I have one mother and my mother has many children. The country has many cities and every city is located in one country.
In our example above, every student "normally" should have one gender. and every gender is for many students.
Natchos and Kareem are two students "many", Male is one.

One To many

Represent Foreignkey in Django:

Because we can not represent all the "many" in the "one" table. It makes a lot of sense to represent the repationship from the many sides.. which means in our example we can't go to the Gender table add a row and say in it: we have a relationship with Natchos , and Kareem and John and Tom ..etc in the male row "record" .. instead we can add a row in the student row and called gender that says these students a relationship with the Gender table in "Male" or in "Female".

many to one

Now to represent the ForeignKey will add it in the Student Field with one main parameter: referring to the model that has ForeignKey relationship "many to one" with it.

from django.db import models

class StudentGender(models.Model):
    gender = models.CharField(max_length=10)
class Student(models.Model):
    name = models.CharField(max_length=30)
    gender = models.ForeignKey(StudentGender, 
   null=True)
Enter fullscreen mode Exit fullscreen mode

Notice in class Student :

gender = models.ForeignKey(Gender, 
   on_delete=models.CASCADE)
Enter fullscreen mode Exit fullscreen mode

That in Django we don't refer to the id of the other model but for the model "class" itself ( in other frameworks such as Flask, we refer to the other model's id). Also, we used null=True to allow the nulls so we can have some students with no gender specified.

OneToOne

one to one is as easy as you can think. this pen is mine and this pen has one owner. I have one husband and my husband has one wife. In our example, every student setting on one desk and every desk is for one student "at least in my country"

Represent OneToOne in Django:

one to one

At this point and because we are going to add one value in either table, it doesn't matter where we add it. But because I think that it is a good idea to add in the Chair table since that the student is the main character, I will add the OneToOne field to the Chair :

class StudentGender(models.Model):
    gender = models.CharField(max_length=10)
    Student = models.OneToOneField(Student, 
   null=True)
class Student(models.Model):
    name = models.CharField(max_length=30)
    gender = models.ForeignKey(StudentGender, 
   null=True)

Notice in class Student :

gender = models.ForeignKey(StudentGender, 
   null=True)
Enter fullscreen mode Exit fullscreen mode

Notice that here I also used "null=True" because as you know, if a chair has no student to set on, we don't have to throw it from the window.

one to one

ManyToMany

Students enroll in many courses and every course is enrolled by many students. in our example, each student can attend many events and every event will be attended by many students. This is simply what a many to many relationships is.

Represent ManyToMany in Django:

In ForeignKey we chose the "one" table and in OneToOne we chose either one. so what table can we choose in many to many? In the normal cases, we create a third table "more like a third wheel in the relationship" that has the id of the first table and the id of the second table as below:

many to many

But!

But!

But!

Django made it easier for us. it is just as easy as adding ManyToOne or foreignKey!Again I will not choose the student.

class Student(models.Model):
    name = models.CharField(max_length=30)
    gender = models.ForeignKey(StudentGender, 
   null=True)

class Chair(models.Model):

chair_number = models.IntegerField()
student = models.ManyToManyField('student')
Enter fullscreen mode Exit fullscreen mode

Here, It seems we have reached the end.
Happy day to you and happy birthday to ME 🎂

References:

Top comments (2)

Collapse
 
incrementis profile image
Akin C.

Hello Manar Abdelkarim,

thank you for your article.
I enjoyed reading it despite having no experience with Django.
In my opinion it is easy to understand and sometimes even funny, e.g. the explanation of the chair with the .gif.
I smiled a bit :D!

By the way I found some minor typos(see "Represent Foreignkey in Django:"):
repationship from the many sides..
Tom ..
"record" ..

Should be(unless you had some other intentions):
relationship from the many sides.
Tom.
"record".

Collapse
 
saaditechlogicians profile image
Saadi-Techlogicians • Edited

Very Well described. Happy Birthday and good luck to you.