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

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

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

Взаимодействие с моделями

Сначала выполните shell_plus команду:

python manage.py shell_plus --print-sql

Для начала создадим новый отдел с именем IT:

d = Department(name='IT', description='Information Technology')
d.save()

Далее создадим двух сотрудников и назначьте их в IT отдел:

e = Employee(first_name='John',last_name='Doe',department=d)
e.save()
e = Employee(first_name='Jane',last_name='Doe',department=d)
e.save()

Попробуем получить доступ к department объекту из employee объекта:

e.department
e.department.description

Мы легко можем получить все отделы следующим запросом.

Department.objects.all()

Все это работает и в обратном направлении, но из-за асимметричности отношений нам необходимо использовать Django метод <object>_set(). Он возвращает QuerySet, например employee_set вернет всех сотрудников отдела:

d = Department.objects.get(id=1)
d.employee_set.all()

Обратите внимание, что мы не определяли employee_set свойство в Department модели. Внутри Django автоматически добавил employee_set свойство в Departmentмодель, когда мы определили отношение «один-ко-многим» с помощью ForeignKey

Метод employee_set.all() возвращает QuerySet, который содержит всех сотрудников, принадлежащих к отделу.

Присоединения сотрудника к отделу

С помощью следующего кода, мы можем получить первого сотрудника:

e = Employee.objects.first()

Для доступа к отделу первого сотрудника вы используете атрибут department:

e.department

В этом случае Django выполняет два запроса. Первый запрос выбирает первого сотрудника, а второй запрос выбирает отдел выбранного сотрудника. Далее по курсу мы расскажем вам, как можно объединить данные запросы.

 

Класс ForeignКey поддерживает следующие дополнительные необязательные параметры:

  • limit_choices_to - позволяет вывести в раскрывающемся списке записей первичной модели, отображаемом в веб-форме, только записи, удовлетворяющие заданным критериям фильтрации. Критерии фильтрации записываются в виде словаря Python, имена элементов которого совпадают с именами полей первичной модели, по которым должна выполняться фильтрация, а значения элементов укажут значения для этих полей. Выведены будут записи, удовлетворяющие всем критериям, заданным в таком словаре (т.е. критерии объединяются по правилу логического И). Мы можем добавить в модель Department новое поле actions. И после укажем Django выводить только рубрики, поле actions которых содержит значение True:
    department = models.ForeignKey(Department, on_delete=models.CASCADE, default=None, limit_choices_to={'actions': True})
  • related_name - имя атрибута записи первичной модели, предназначенного для доступа к связанным записям вторичной модели, в виде строки. По умолчанию обратное отношение будет называться ****_set

    Однако вы можете изменить имя обратного отношения с помощью атрибута related_name.

        department = models.ForeignKey(Department, on_delete=models.CASCADE, default=None,
                                       related_name='test')

    Если доступ из записи первичной модели к связанным записям вторичной модели не требуется, можно указать Django не создавать такой атрибут и тем самым немного сэкономить системные ресурсы. Для этого достаточно присвоить параметру related_name = "+". Если параметр не указан, то атрибут такого рода получит стандартное имя вида <имя связанной вторичной модели>_sеt

  • related_query_name - имя фильтра, которое будет применяться во вторичной модели для фильтрации по значениям из записи первичной модели:
    department = models.ForeignKey(Department, on_delete=models.CASCADE, default=None,
                                   related_query_name='entry')

  • to_field - имя поля первичной модели, по которому будет выполнена связь, в виде строки . Такое поле должно быть помечено как уникальное (параметр unique конструктора должен иметь значение True). Если параметр не указан, связывание выполняется по ключевому полю первичной модели - неважно, созданному явно или не явно;
  • db_constraint - если True, то в таблице базы данных будет создана связь, позволяющая сохранять ссылочную целостность, если False, ссылочная целостность будет поддерживаться только на уровне Django. Значение по умолчанию - True. Менять его на False имеет смысл, только если модель создается на основе уже существующей базы с некорректными данными.

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

Здравствуйте, Илья. Я правильно понял, что при отношении один-к-одному, родительской считается та таблица, которая связывается с другой посредством OneToOneField, а при отношении один-ко-многим, родительской считается та таблица, с которой связываются посредством ForeignKey? 

@Агаси_Мироян, Ага, вы все верно поняли. Когда один к одному, то родительская в нашем случае работники, дочерняя - контакты. А когда один ко многим то департамент родитель, а сотрудники дочерняя.

Разве не python manage.py shell_plus --print-sql нужно выполнять?

@Григорий_Кожанов, верно, поправили лекцию, спасибо!