如何使用SQLAlchemy

时间:2018-12-13 13:05:33

标签: python 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)唯一约束失败: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()选项,但没有解决。

请解决此问题。

1 个答案:

答案 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()

因此,如果数据库中已经存在现有标签,那么现在将使用它;如果没有,请使用新标签。