Использование OneToOneField в Django

Я очень запутался в использовании OnetoOneField. Я думал, что он предназначен для случая, когда данная запись может иметь только 1 ссылку на другую таблицу. Например, у дочерней записи есть 1 родительская.

Но похоже, что Django делает поле, определенное как OneToOne, первичным ключом вашей таблицы, что означает, что оно имеет ограничение Unique. Это не имеет никакого смысла. У любого ребенка есть только 1 родитель. Но может быть более одного ребенка с одним и тем же родителем. FK родителя не будет уникальным во всей таблице Child

Я хотел использовать OneToOne вместо ForeignKey, чтобы обеспечить аспект "один к одному", в отличие от ForeignKey, который является 1 ко многим (любой данный ребенок может иметь более одного родителя).

Я не прав в своем понимании? Должен ли я вернуться к использованию ForeignKey и просто убедиться, что мой код обеспечивает 1-1?

Я нашел эти другие ссылки, в которых задается тот же вопрос, но не уверен, что увидел окончательный ответ Зачем кому-то устанавливать primary_key=True для отношения "один к одному" (OneToOneField)? OneToOneField() vs ForeignKey() в Django

A OneToOneField может немного ввести в заблуждение, на самом деле это поле ноль/один-к-одному. Обычно оно используется для связи экземпляров модели A с экземплярами модели B, но при этом два экземпляра A не могут ссылаться на один и тот же экземпляр B. Типичный случай использования - это, например, если у вас есть модель Employees, и для некоторых Employees вам нужно хранить дополнительные данные. Но это часто является некоторым антипаттерном: если у вас есть контроль над моделью B (потому что она не реализована в другом пакете), вы не можете добавить (nullable) поля в B, и тогда вы можете сделать модель A с дополнительными данными и указать OneToOneField из A в B. Это также можно использовать, если количество полей будет большим, а количество записей B, имеющих связанную запись A, небольшим. В этом случае создание дополнительных nullable-полей может сильно раздуть базу данных. В пакетах Django по умолчанию (django.contrib) она вообще не используется.

A OneToOneField however has a use-case for which Django uses a OneToOneField in a hidden matter: model inheritance [Django-doc]. Indeed, if you make two models:

class Foo(models.Model):
    pass


class Bar(Foo):
    pass

Тогда это две конкретные модели. Django реализует это, создав две таблицы, одну для foo и одну для bar. Первичным ключом Bar будет OneToOneField, который ссылается на таблицу Foo. Таким образом, они разделяют одно и то же "пространство идентификаторов", и это также гарантирует, что для одного Foo не будет создано двух Bar. Однако это не препятствует созданию записи Qux с тем же id, если Qux также является подклассом Foo, так что это не "идеальный" способ представления наследования. Кроме того, наследование в реляционных базах данных часто также не является хорошей идеей, поскольку требует дополнительных JOIN.

Подведем итоги: OneToOneField часто используются для добавления данных в уже существующую модель, которую мы не очень контролируем, или когда количество записей с дополнительными данными невелико и может привести к взрыву хранилища. Но использовать их следует с умом.

Анекдот: Я пользовался этим, потому что Django не очень ясно показывает, какая сессия принадлежит какому пользователю. Это кодируется в данных сессии, но нелегко отфильтровать, например, какие сессии принадлежат определенному пользователю. Затем я использовал OneToOneField для ссылки на Session, чтобы не создавать много лишних записей.

Вернуться на верх