Chapter 3. Django Models and Database

Django Models – ForeignKey (OneToMany Relationship)

Django Models – ForeignKey (OneToMany Relationship)
Tag:

To make a One-To-Many relationship, Django uses ForeignKey. There are two key arguments you need to specify.

  1. Related model name
  2. On_delete argument

As explained on the previous page, by specifying a related model name through the ForeignKey field, Django connects the field with the ID of the related model. The on_delete argument is used to define the behavior when an object of the related model is deleted.

There are three possible values for the on_delete argument.

  • CASCASE: deletes the object containing the ForeignKey.
  • PROTECT: prevents deletion of the referenced object by raising ProtectedError
  • RESTRICT: prevents deletion of the referenced object by raising RestrictedError

As the possible values are available in django.db.models, you need to write on_delete=models.CASCADE.

Practice

Objective:
Learn how to use ForeignKey

In this practice, we'll explain how to use ForeignKey to create One-To-Many Relationship. In this case example, we'll add a division field in the Employee model by connecting it with the Division model.

1. Add a new field in the Employee model in models.py

Edit the Employee model in the models.py file to connect with the Division model.

  • Field name: division
  • Field type: ForeignKey
  • Related model name: Division
  • On_delete: models.CASCADE

The yellow line below is the new code.

employee_learning/models.py
from django.db import models
import datetime

class Employee(models.Model):

    PRIORITIES=[('H','High'), ('M','Medium'), ('L','Low'),]

    name=models.CharField(max_length=25, verbose_name="Employee Name")
    priority=models.CharField(max_length=1, choices=PRIORITIES, default="M", verbose_name="Learning Priorities")
    reg_date=models.DateField(default=datetime.date.today, verbose_name="Data Registration Date")
    division=models.ForeignKey(Division, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

2. Move the Division model before the Employee model in models.py

Cut the code of the Division model and paste the code before the Employee model in the models.py file. This is needed because the Employee model will refer to the Division model in the new field.

employee_learning/models.py
from django.db import models
import datetime

class Division(models.Model):
      :
    def __str__(self):
        return self.div_name

class Employee(models.Model):
      :

3. Run the makemigrations command

Run the makemigrations command.

Command Line - INPUT
python manage.py makemigrations employee_learning

As there are existing records, you'll encounter the message below.

Command Line - INTERACTIVE
It is impossible to add a non-nullable field 'division' to employee without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option: 

Answer 1 at this time. Then, the prompt is asking what data should be filled in.

Command Line - INTERACTIVE
Select an option: 1
Please enter the default value as valid Python.
The datetime and django.utils.timezone modules are available, so it is possible to provide e.g. timezone.now as a value.
Type 'exit' to exit this prompt
>>>

Here, you need to be careful. You should not input the data that is not available. As we need to input an available ID created in the Division model, type "1" for now.

Command Line - INTERACTIVE
>>> 1
Migrations for 'employee_learning':
employee_learning/migrations/0007_employee_division.py
- Add field division to employee

4. Migrate the model into the database and run the runserver

Complete the migration and run the runsever command.

Command Line - INPUT
python manage.py migrate
python manage.py runserver

5. Check the Django admin site

You can see that the Division model and the Employee model are connected. The employee model also reflects the data as we temporality input "1" for existing data. ID:1 is "Product Development" in this case.

Django-Models--ForeignKey-OneToMany-Relationship

To make a One-To-Many relationship, Django uses ForeignKey. There are two key arguments you need to specify.

  1. Related model name
  2. On_delete argument

As explained on the previous page, by specifying a related model name through the ForeignKey field, Django connects the field with the ID of the related model. The on_delete argument is used to define the behavior when an object of the related model is deleted.

There are three possible values for the on_delete argument.

  • CASCASE: deletes the object containing the ForeignKey.
  • PROTECT: prevents deletion of the referenced object by raising ProtectedError
  • RESTRICT: prevents deletion of the referenced object by raising RestrictedError

As the possible values are available in django.db.models, you need to write on_delete=models.CASCADE.

Practice

Objective:
Learn how to use ForeignKey

In this practice, we'll explain how to use ForeignKey to create One-To-Many Relationship. In this case example, we'll add a division field in the Employee model by connecting it with the Division model.

1. Add a new field in the Employee model in models.py

Edit the Employee model in the models.py file to connect with the Division model.

  • Field name: division
  • Field type: ForeignKey
  • Related model name: Division
  • On_delete: models.CASCADE

The yellow line below is the new code.

employee_learning/models.py
from django.db import models
import datetime

class Employee(models.Model):

    PRIORITIES=[('H','High'), ('M','Medium'), ('L','Low'),]

    name=models.CharField(max_length=25, verbose_name="Employee Name")
    priority=models.CharField(max_length=1, choices=PRIORITIES, default="M", verbose_name="Learning Priorities")
    reg_date=models.DateField(default=datetime.date.today, verbose_name="Data Registration Date")
    division=models.ForeignKey(Division, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

2. Move the Division model before the Employee model in models.py

Cut the code of the Division model and paste the code before the Employee model in the models.py file. This is needed because the Employee model will refer to the Division model in the new field.

employee_learning/models.py
from django.db import models
import datetime

class Division(models.Model):
      :
    def __str__(self):
        return self.div_name

class Employee(models.Model):
      :

3. Run the makemigrations command

Run the makemigrations command.

Command Line - INPUT
python manage.py makemigrations employee_learning

As there are existing records, you'll encounter the message below.

Command Line - INTERACTIVE
It is impossible to add a non-nullable field 'division' to employee without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option: 

Answer 1 at this time. Then, the prompt is asking what data should be filled in.

Command Line - INTERACTIVE
Select an option: 1
Please enter the default value as valid Python.
The datetime and django.utils.timezone modules are available, so it is possible to provide e.g. timezone.now as a value.
Type 'exit' to exit this prompt
>>>

Here, you need to be careful. You should not input the data that is not available. As we need to input an available ID created in the Division model, type "1" for now.

Command Line - INTERACTIVE
>>> 1
Migrations for 'employee_learning':
employee_learning/migrations/0007_employee_division.py
- Add field division to employee

4. Migrate the model into the database and run the runserver

Complete the migration and run the runsever command.

Command Line - INPUT
python manage.py migrate
python manage.py runserver

5. Check the Django admin site

You can see that the Division model and the Employee model are connected. The employee model also reflects the data as we temporality input "1" for existing data. ID:1 is "Product Development" in this case.

Django-Models--ForeignKey-OneToMany-Relationship

Tag: