环境: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)唯一约束失败:tags.name [SQL:'INSERT INTO tags(name)VALUES(?)'] [参数:(('x',) ,('a',))](此错误的背景位于:http://sqlalche.me/e/gkpj)
我猜想session.add
总是在父元素有子元素时尝试插入,这里显示的“子元素”可能是Tag
。
但是我真的想做的只是针对引用新文章数据和任何现有标签的taggings
表创建新记录。
我了解了cascade in the official document,并尝试从save-update
中删除relationship()
选项,但没有解决。
请解决此问题。
答案 0 :(得分:0)
考虑到您对我的问题的回答,您应该添加检查来自数据库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()
因此,如果数据库中已经存在现有标签,那么现在将使用它;如果没有,请使用新标签。