Продвинутый Django 5 для продолжающих

Прогресс по курсу:  0/193

2.3 Связь One-To-Many (Один ко многим)
2 из 2 шагов пройдено

Введение в отношения «один-ко-многим» в 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.

 


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
Нет обсуждений. Начните первое.