sqlalchemyのコミット前のobjectに注意

N:1のN側の話

sqlalchemyのrelationはinstrumented listという形で管理されている。

N:1のN側の方の話です。(以下のコードではgroup.usersのこと)

class Group(Base):
    __tablename__ = "groups"
    id = sa.Column(sa.Integer(), primary_key=True, nullable=False)
    name = sa.Column(sa.String(255), unique=True, nullable=False)

class User(Base):
    __tablename__ = "users"
    id = sa.Column(sa.Integer(), primary_key=True, nullable=False)
    name = sa.Column(sa.String(255), unique=True, nullable=False)
    group_id = sa.Column(sa.Integer(), sa.ForeignKey(Group.id))
    group = orm.relationship(Group, backref="users")

# group = Group(name="group)
# group.users.append(User(name="foo"))
# User(name="boo", group=group)
## len(group.users) # => 3

以下の方法でN:1のN側のオブジェクトに値を追加できる。

同一のオブジェクトが複数挿入されてしまう場合も(コミット前)

ただし、以下のような場合に、期待した大きさとは異なる長さを返すので注意。

group = Group(name="group")
user = User(name="user00", group=group)
group.users.append(user)

len(group.users) # => 2
assert group.users[0] == group.users[1]

同一のオブジェクトがコンストラクタの引数とプロパティのappendによって挿入されてしまう。 これはDBにコミットされた段階では直る。

参考