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)")
Вернуться на верх