Введение в отношения «один-ко-многим» в Django
В отношении «один-ко-многим» строка в таблице связана с одной или несколькими строками в другой таблице. Например, в отделе может быть один или несколько сотрудников, и каждый сотрудник принадлежит к одному отделу.
Отношения между отделами и сотрудниками представляют собой отношения «один-ко-многим». И наоборот, отношения между сотрудниками и отделами представляют собой отношения «многие-к-одному».
Для создания связи такого типа в классе вторичной модели следует объявить поле типа ForeignКey. Вот формат конструктора этого класса:
ForeignKey(<связываемая первичная модель>, on_delete=<поведение при удалении записи>, [<остальные параметры>])
Чтобы создать отношение «один-ко-многим» в Django, вы используете ForeignKey. Например, в следующем примере используется ForeignKey для создания отношения «один ко многим» между моделями Department и Employee:
from django.db import models
class Contact(models.Model):
phone = models.CharField(max_length=50, unique=True)
address = models.CharField(max_length=50)
def __str__(self):
return self.phone
class Department(models.Model):
name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.name
class Employee(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
contact = models.OneToOneField(Contact, on_delete=models.CASCADE, null=True)
department = models.ForeignKey(Department, on_delete=models.CASCADE, default=None)
def __str__(self):
return f'{self.first_name} {self.last_name}'
Как это работает. Сначала определите Department класс модели. Во-вторых, измените Employee класс, добавив отношение «один ко многим» с помощью ForeignKey:
department = models.ForeignKey(Department, on_delete=models.CASCADE)
В ForeignKey, мы передаем в Department качестве первого аргумента и on_delete аргумент ключевого слова как models.CASCADE, что при удалении отдела все сотрудники, связанные с отделом, также удаляются. Даже если в hr_employees таблице нет строк, Django также запрашивает у вас значение по умолчанию (default=None).
Вторым параметром on_delete указывается поведение фреймворка в случае, если будет выполнена попытка удалить запись первичной модели, на которую ссылаются какие-либо записи вторичной модели. Параметру присваивается значение одной
из переменных, объявленных в модуле django.db.models:
CASCADE- удаляет все связанные записи вторичной модели (каскадное удаление);PROTECT- возбуждает исключениеProtectedErrorиз модуляdjango.db.models, тем самым предотвращая удаление записи первичной модели;SET_NULL- заносит в поле внешнего ключа всех связанных записей вторичной модели значениеnull. Сработает только в том случае, если поле внешнего ключа объявлено необязательным к заполнению на уровне базы данных (параметрnullконструктора поля имеет значениеTrue);SET_DEFAULT- заносит в поле внешнего ключа всех связанных записей вторичной модели заданное для него значение по умолчанию. Сработает только в том случае, если у поля внешнего ключа было указано значение по умолчанию (оно задается параметромdefaultконструктора поля);SET(<значение>)- заносит в поле внешнего ключа указанное значение:Также можно указать ссылку на функцию, не принимающую параметров и возвращающую значение, которое будет записано в поле:department = models.ForeignKey(Department, on_delete=models.SET(1))def get_first_department(): return Department.objects.first() department = models.ForeignKey(Department, on_delete=models.SET(get_first_department))DO_NOTHING- ничего не делает.
Выполните миграцию с помощью makemigrations команды:
python manage.py makemigrations
Если в hr_employee таблице есть какие-либо строки, вам необходимо удалить их все перед переносом новых миграций:
python manage.py shell_plus
>>> Employee.objects.all().delete()
Затем вы можете внести изменения в базу данных с помощью migrate команды:
python manage.py migrate
В базе данных Django создает hr_department и добавляет department_id столбец в hr_employee таблицу. Столбец department_id таблицы hr_employee ссылается на id столбец таблицы hr_department.