Зачем мне нужны отношения и внешний ключ для отношений «многие к одному»? - PullRequest
0 голосов
/ 14 февраля 2019

В документах для отношений SQLAlchemy для многих к одному показан следующий пример:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)

Многие родители для одного ребенка. Тогда, когдаесли мы создадим Parent, нам нужно заполнить child_id и child, что кажется излишним?Является ли это обязательным, или какова цель каждой вещи?

child = Child()
Parent(child_id=child, child=child)

Кроме того, в Flask-SQLAlchemy есть этот пример для простого отношения , в котором он создает сообщение, подобное этому:

Post(title='Hello Python!', body='Python is pretty cool', category=py)

без предоставления category_id.Если я воспроизведу этот сценарий, значение category_id будет равно None.

Для целей создания новых объектов, таких как Parent(child=child), будет достаточно добавить foreign_keys=[child_id] или оно будет иметь дополнительные последствия?

1 Ответ

0 голосов
/ 14 февраля 2019

не является обязательным;Вам не нужно заполнять оба.Установка внешнего ключа для связанного экземпляра может быть ошибкой, ожидающей своего проявления.Единственное, что вам нужно сделать, это

child = Child()
parent = Parent(child=child)

После этого parent.child_id - это None, но они представляют объектную часть ORM просто отлично.parent.child является ссылкой на созданный child.Они не были сохранены в базе данных и не имеют идентификаторов, кроме идентификатора объекта Python.Только когда вы добавляете их в Session и сбрасываете изменения в базу данных, они получают удостоверение, потому что они используют сгенерированные суррогатные ключи.Вот где происходит сопоставление объектного мира с миром отношений.SQLAlchemy автоматически заполняет parent.child_id, так что их отношения также записываются в базе данных (обратите внимание, что это не то, что означает «реляционный» в реляционной модели).

Возвращаясь к примеру, добавляя некоторые подсказки печатиотслеживать, что происходит и когда:

child = Child()
parent = Parent(child=child)
print(parent.child_id)  # None
session.add(parent)
session.flush()  # Send changes held in session to DB
print(parent.child_id)  # The ID assigned to child

Вы также можете изменить ситуацию: у вас может быть идентификатор существующего Child, но не фактический объект.В этом случае вы можете просто назначить child_id самостоятельно.

Итак, чтобы ответить на заголовок: вам не нужен ORM relationship, чтобы иметь отношение внешнего ключа БД, но вы можете использовать его длясопоставить связь БД с объектным миром.

...