On Sun, Oct 7, 2018 at 7:11 PM Alex Rothberg <
agrot...@gmail.com> wrote:
>
> Okay so I investigated / thought about this further. The issue is that while I do have a relationship between the various models, some of the relationships are viewonly since I have overlapping fks.
>
> For example I have a model Employee, which has fks: department_id, title_id, and fund_id. The related models are Department (fk department_id), Title (fk department_id and title_id) , Fund (fk fund_id) and FundTitle (fk department_id, title_id and fund_id). I have set FundTitle to viewonly. When updating / creating an Employee, I do create and add a new FundTitle to the session, however I don't assign it to the employee as the relationship is viewonly. If I don't flush before making the assignment, the final flush / commit attempts to update / create the employee before creating the FundTitle.
let's work with source code that is runnable (e.g. MCVE). Below is
the model that it seems you are describing, and then there's a
demonstration of assembly of all those components using relationships,
a single flush and it all goes in in the correct order, all FKs are
nullable=False.
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
title_id = Column(ForeignKey('
title.id'), nullable=False)
department_id = Column(ForeignKey('
department.id'), nullable=False)
fund_id = Column(ForeignKey('
fund.id'), nullable=False)
department = relationship("Department")
title = relationship("Title")
fund = relationship("Fund")
class Title(Base):
__tablename__ = 'title'
id = Column(Integer, primary_key=True)
department_id = Column(ForeignKey('
department.id'), nullable=False)
department = relationship("Department")
class Department(Base):
__tablename__ = 'department'
id = Column(Integer, primary_key=True)
class Fund(Base):
__tablename__ = 'fund'
id = Column(Integer, primary_key=True)
title_id = Column(ForeignKey('
title.id'), nullable=False)
department_id = Column(ForeignKey('
department.id'), nullable=False)
department = relationship("Department")
title = relationship("Title")
class FundTitle(Base):
__tablename__ = 'fund_title'
id = Column(Integer, primary_key=True)
title_id = Column(ForeignKey('
title.id'), nullable=False)
department_id = Column(ForeignKey('
department.id'), nullable=False)
fund_id = Column(ForeignKey('
fund.id'), nullable=False)
department = relationship("Department")
title = relationship("Title")
fund = relationship("Fund")
e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
Base.metadata.create_all(e)
s = Session(e)
d1 = Department()
t1 = Title(department=d1)
f1 = Fund(department=d1, title=t1)
ft1 = FundTitle(title=t1, department=d1, fund=f1)
e1 = Employee(title=t1, department=d1, fund=f1)
s.add_all([d1, t1, f1, ft1, e1])
s.commit()
the INSERTs can be ordered naturally here and the unit of work will do
that for you if you use relationship:
BEGIN (implicit)
2018-10-08 10:18:38,750 INFO sqlalchemy.engine.base.Engine INSERT INTO
department DEFAULT VALUES RETURNING
department.id
2018-10-08 10:18:38,750 INFO sqlalchemy.engine.base.Engine {}
2018-10-08 10:18:38,753 INFO sqlalchemy.engine.base.Engine INSERT INTO
title (department_id) VALUES (%(department_id)s) RETURNING
title.id
2018-10-08 10:18:38,753 INFO sqlalchemy.engine.base.Engine {'department_id': 1}
2018-10-08 10:18:38,757 INFO sqlalchemy.engine.base.Engine INSERT INTO
fund (title_id, department_id) VALUES (%(title_id)s,
%(department_id)s) RETURNING
fund.id
2018-10-08 10:18:38,757 INFO sqlalchemy.engine.base.Engine
{'title_id': 1, 'department_id': 1}
2018-10-08 10:18:38,760 INFO sqlalchemy.engine.base.Engine INSERT INTO
employee (title_id, department_id, fund_id) VALUES (%(title_id)s,
%(department_id)s, %(fund_id)s) RETURNING
employee.id
2018-10-08 10:18:38,761 INFO sqlalchemy.engine.base.Engine
{'title_id': 1, 'department_id': 1, 'fund_id': 1}
2018-10-08 10:18:38,763 INFO sqlalchemy.engine.base.Engine INSERT INTO
fund_title (title_id, department_id, fund_id) VALUES (%(title_id)s,
%(department_id)s, %(fund_id)s) RETURNING
fund_title.id
2018-10-08 10:18:38,764 INFO sqlalchemy.engine.base.Engine
{'title_id': 1, 'department_id': 1, 'fund_id': 1}
2018-10-08 10:18:38,766 INFO sqlalchemy.engine.base.Engine COMMIT