如何使用SQLAlchemy将关于每个现有数据的新记录插入到关联表中



环境:python3.7、SQLAlchemy1.3、SQLite3.22

我定义了2个表和1个关联表,如下所示。

# associative table
taggings = Table('taggings', Base.metadata, 
Column('id', Integer, primary_key=True),
Column('article_id', Integer, ForeignKey('articles.id'), nullable=False),
Column('tag_name', Integer, ForeignKey('tags.name'), nullable=False),
)
# mapper about article master
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
...
tags = relationship('Tag', secondary=taggings, backref='articles')
# mapper about tag master
class Tag(Base):
__tablename__ = 'tags'
name = Column(String, primary_key=True)

现在我想能够创建一篇新的文章,用任何现有的标签进行标记。所以,我试着。。。

new_one = Article(**payload.article)
new_one.tags = [Tag(name=x) for x in payload.tags]  # these tags are already stored in database.
sesion.add(new_one)
session.flush()

并测试它,但我得到了一个关于UNIQUE约束的错误。细节在这里。

***sqlalchemy.exc.IntegrityError:(sqlite3.IntegrityError(UNIQUE约束失败:tags.name[SQL:"INSERT INTO tags(name(VALUES(?("][参数:(('x',(,('a',((](此错误的背景信息:http://sqlalche.me/e/gkpj)

我猜session.add总是在父元素有子元素时尝试插入,这里出现的"子元素"可能是Tag。但我真正想做的只是针对引用新文章数据和任何现有标记的taggings表创建新记录。

我在官方文件中读到了级联,并尝试从relationship()中删除save-update选项,但没有解决。

请告诉我如何解决这个问题。

考虑到您对我的问题的回答,您应该添加检查payload中的标记是否已经在数据库中。所以应该是这样的:

new_one = Article(**payload.article)
tags = []
for tag_name in payload.tags:
tag = session.query(Tag).filter_by(name=tag_name).first()
# tag will be None if it does not exist in the database
tags.append(tag if tag else Tag(name=tag_name))
new_one.tags = tags
sesion.add(new_one)
session.flush()

因此,现在您将使用现有标记(如果它已经在数据库中(,或者创建一个新标记(如果不是(。

最新更新