【问题标题】:Sqlalchemy 0.7.10 silently omits duplicate entries in many-to-many relationSqlalchemy 0.7.10 默默地忽略了多对多关系中的重复条目
【发布时间】:2013-08-26 09:54:45
【问题描述】:

我正在尝试使用 sqlalchemy 0.7.10 处理多对多关系。我的问题是炼金术默默地忽略了将重复条目插入到关联表中。期望的行为是从 db 获取 DB Duplicate Entry 错误并通知用户。

以下是模型:

class Node(BASE):
    __tablename__ = "nodes"
    .....

class ZoneNodeAssociation(BASE):
    __tablename__ = "zone_node_association"
    node_id = Column(Integer, ForeignKey('nodes.id'),
                     primary_key=True, nullable=False)
    zone_id = Column(Integer, ForeignKey('zones.id'),
                     primary_key=True, nullable=False)    

class Zone(BASE):
    __tablename__ = "zones"
    id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
    name = Column(String(255), unique=True)
    nodes = relationship("Node",
                         secondary="zone_node_association",
                         backref="zones",)

以及行动:

def zone_add_node(context, zone_id, node_id):
    session = get_session()
    with session.begin():
        zone_ref = _zone_get(context, zone_id, session)
        node_ref = _node_get(context, node_id, session)
        zone_ref.nodes.append(node_ref)
        zone_ref.save(session=session)

第一次按预期添加关联表条目,但是当我尝试添加重复项时,它只是以没有错误结束。

当我直接插入关联表时,比如

session = get_session()
with session.begin():
    association_entry = models.ZoneNodeAssociation()
    association_entry.update({'zone_id': zone_id, 'node_id': node_id})
    association_entry.save(session=session)

它的行为符合预期,但我不喜欢这种方式,因为如果其中一个 id 不存在,我会收到一个 Integrity 错误,而且我不知道究竟哪个 Id 是错误的。所以我想改用第一种方法。

我发现的所有类似问题都有倒置问题——他们想默默地忽略重复项,但该死的我需要错误! =)

我还在 sqlalchemy 更改日志中发现了一些内容: http://docs.sqlalchemy.org:8000/en/rel_0_7/changelog/changelog_05.html#change-1a61f53a8bf148ab3f8311330af61a4e 但据我了解,它已在 0.5 版本中修复,我使用的是 0.7.10

更新:

我尝试在单独的环境中玩游戏并得到相同的行为。这是代码: https://gist.github.com/max-lobur/6366708

【问题讨论】:

  • 您是否尝试过在两者之间进行冲洗?
  • 刚试过 zone_ref.nodes.append(node_ref) session.flush() zone_ref.save(session=session) 结果是一样的。我在想是否可以通过一些全局 SqlAlchemy 配置来指定应该省略重复项?如果是这样,那么我该如何为我的特定表覆盖它
  • 我不确定我是否正确,因为您没有提供所有代码。我创建的内容确实引发了异常:pastebin.com/QVF3Fzt0 尝试并尝试发现差异。如果这没有帮助,请创建一个像我一样的完整示例,但其行为与预期不符。
  • 我从您的示例中了解到,您第一次使用 nodes.append 创建关联,第二次使用直接写入关联表。但我总是使用nodes.append,对我来说,添加重复项时它不会抛出异常。我做了一个直接使用关联表的例子来表明它按预期工作。但是当我使用追加时出现了我的问题。无论如何,感谢您抽出宝贵的时间,我想我需要像您的示例一样将我的代码与项目隔离,然后重试。我很确定原因是一些特定于项目的配置。
  • 我发现它与项目无关,它在单独的环境中的行为方式相同。 gist.github.com/max-lobur/6366708 这是我尝试过的。据我了解,添加重复项时,SA 不会为关联表生成插入语句,因此 DB 当然不会生成异常。

标签: python sqlalchemy many-to-many


【解决方案1】:

我认为您需要在关系中指定lazy='dynamic'。

nodes = relationship("Node", secondary="zone_node_association", backref="zones", lazy='dynamic')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 2018-05-03
    相关资源
    最近更新 更多