SQLAlchemy - Передача первичного ключа, сгенерированного в DDL, дочерней модели через отношения
В настоящее время у меня определено отношение родитель/потомок между таблицей Invoice/Item.
При выполнении следующего кода:
with Session(engine) as session:
invoice = Invoice(INV_STORE=99, items=[Item(LINE_ITEM=1, BARCODE=1234567),
Item(LINE_ITEM=2, BARCODE=1234567)])
session.add(invoice)
session.commit()
Я получаю следующую ошибку:
[SQL Server]Cannot insert the value NULL into column '...'
[SQL: INSERT INTO [ITEM] ([INV_STORE], [LINE_ITEM], [BARCODE]) VALUES (?, ?, ?)]
[parameters: (99, 1, 1234567)]
Мой объект счета-фактуры создается идеально, похоже, что значения столбцов, сгенерированные DDL, не заполняют дочерний объект автоматически, только значение магазина, которое я передал объекту Invoice (обратите внимание на отсутствие INV_NUM в операторе вставки). Может быть, я упускаю что-то простое?
К сожалению, используемая нами устаревшая база данных требует, чтобы отношения между таблицами были настроены как таковые, и для поля Invoice.INV_NUM нет автоинкремента.
Вот конфигурация моей модели:
class Invoice(Base):
__tablename__ = 'INVOICE'
INV_STORE = Column(Integer, name='INV_STORE', primary_key=True, default=1)
INV_NUM = Column(Integer,
name='INV_NUM',
default=text(f"(SELECT MAX(INV_NUM) + 1 FROM INVOICE WHERE INV_STORE = {INV_STORE})"),
primary_key=True))
...
items = relationship('Item',
backref='Invoice',
primaryjoin='Invoice.INV_STORE == Item.INV_STORE and Invoice.INV_NUM == Item.INV_NUM')
И ребенок, пункт:
class Item(Base):
__tablename__ = 'ITEM'
INV_STORE = Column(SmallInteger, ForeignKey('INVOICE.INV_STORE'), primary_key=True)
INV_NUM = Column(Integer, ForeignKey('INVOICE.INV_NUM'), primary_key=True)
LINE_ITEM = Column(Integer, name='LINE_ITEM', primary_key=True)
...
Похоже, что синтаксис соединения был неправильным? Я рефакторизовал соединение до следующего вида, и оно работает как шарм:
class Invoice(Base):
__tablename__ = 'INVOICE'
INV_STORE = Column(Integer, name='INV_STORE', primary_key=True, default=1)
INV_NUM = Column(Integer,
name='INV_NUM',
default=text(f"(SELECT MAX(INV_NUM) + 1 FROM INVOICE WHERE INV_STORE = {INV_STORE})"),
primary_key=True)
items = relationship('Item',
backref='Invoice',
primaryjoin="and_(Invoice.INV_NUM==Item.INV_NUM, "
"Invoice.INV_STORE==Item.INV_STORE)")