如何避免在 SQLAlchemy - python 的多对多关系表中添加重复项?
Posted
技术标签:
【中文标题】如何避免在 SQLAlchemy - python 的多对多关系表中添加重复项?【英文标题】:How to avoid adding duplicates in a many-to-many relationship table in SQLAlchemy - python? 【发布时间】:2013-04-08 17:45:27 【问题描述】:我正在处理与 sqlalchemy 的多对多关系。我的问题是如何避免在多对多关系表中添加重复的对值。
为了让事情更清楚,我将使用官方 SQLAlchemy 文档中的示例。
Base = declarative_base()
Parents2children = Table('parents2children', Base.metadata,
Column('parents_id', Integer, ForeignKey('parents.id')),
Column('children_id', Integer, ForeignKey('children.id'))
)
class Parent(Base):
__tablename__ = 'parents'
id = Column(Integer, primary_key=True)
parent_name = Column(String(45))
child_rel = relationship("Child", secondary=Parents2children, backref= "parents_backref")
def __init__(self, parent_name=""):
self.parent_name=parent_name
def __repr__(self):
return "<parents(id:'%i', parent_name:'%s')>" % (self.id, self.parent_name)
class Child(Base):
__tablename__ = 'children'
id = Column(Integer, primary_key=True)
child_name = Column(String(45))
def __init__(self, child_name=""):
self.child_name= child_name
def __repr__(self):
return "<experiments(id:'%i', child_name:'%s')>" % (self.id, self.child_name)
###########################################
def setUp():
global Session
engine=create_engine('mysql://root:root@localhost/db_name?charset=utf8', pool_recycle=3600,echo=False)
Session=sessionmaker(bind=engine)
def add_data():
session=Session()
name_father1=Parent(parent_name="Richard")
name_mother1=Parent(parent_name="Kate")
name_daughter1=Child(child_name="Helen")
name_son1=Child(child_name="John")
session.add(name_father1)
session.add(name_mother1)
name_father1.child_rel.append(name_son1)
name_daughter1.parents_backref.append(name_father1)
name_son1.parents_backref.append(name_father1)
session.commit()
session.close()
setUp()
add_data()
session.close()
使用此代码,插入表中的数据如下:
父母表:
+----+-------------+
| id | parent_name |
+----+-------------+
| 1 | Richard |
| 2 | Kate |
+----+-------------+
儿童桌:
+----+------------+
| id | child_name |
+----+------------+
| 1 | Helen |
| 2 | John |
+----+------------+
Parents2children 表
+------------+-------------+
| parents_id | children_id |
+------------+-------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 1 |
+------------+-------------+
如您所见,最后一个表中有重复项...如何防止 SQLAlchemy 添加这些重复项?
我试过把关系(“Child”,secondary=...,collection_class=set)显示这个错误: em>
AttributeError: 'InstrumentedSet' object has no attribute 'append'
【问题讨论】:
您不能在重新添加之前检查关系是否已经存在吗? 【参考方案1】:将PrimaryKeyConstraint(或UniqueConstraint)添加到您的relationship
表中:
Parents2children = Table('parents2children', Base.metadata,
Column('parents_id', Integer, ForeignKey('parents.id')),
Column('children_id', Integer, ForeignKey('children.id')),
PrimaryKeyConstraint('parents_id', 'children_id'),
)
当您尝试提交从双方添加的关系时,您的代码将生成错误。非常推荐这样做。
为了不产生错误,请先检查:
if not(name_father1 in name_son1.parents_backref):
name_son1.parents_backref.append(name_father1)
【讨论】:
这几乎可以工作 :) 但是我如何防止 SQL Alchemy 在“children”表中添加相同的条目?? “避免在“children”表中添加相同条目的解决方案是什么?以上是关于如何避免在 SQLAlchemy - python 的多对多关系表中添加重复项?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Python 在 AWS Lambda 上运行 SQLAlchemy
如何在 python 中使用 SQLalchemy 在数据库中有新条目时运行脚本?