【问题标题】:How can I do insert a new record to an associative table about each existing data by using SQLAlchemy如何使用 SQLAlchemy 将新记录插入到有关每个现有数据的关联表中
【发布时间】:2018-12-13 13:05:32
【问题描述】:

环境: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 (?)'] [parameters: (('x',) , ('a',))](此错误的背景:http://sqlalche.me/e/gkpj

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

我阅读了有关cascade in the official document 的信息,并尝试从relationship() 中删除save-update 选项,但未解决。

请问如何解决这个问题。

【问题讨论】:

  • 看来您正在创建数据库中已经存在的标签。您可以查看数据库(或在代码中打印),看看您是否不尝试创建相同的标签(只要标签的名称是主键,所以它应该是唯一的)?
  • 啊,是的,标签是存在的。我徘徊通过session.add 使用现有标签创建新文章。那么我可以通过使用 SQLAlchemy 来做到这一点吗?我知道我可以显式地为taggings 表创建关联记录...

标签: python sqlalchemy


【解决方案1】:

考虑到您对我的问题的回答,您应该添加检查 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()

所以现在你将使用现有标签,如果它已经在数据库中,或者创建一个新标签。

【讨论】:

  • 感谢您的回复。我发现我需要进行现有检查。
  • 但是这种方式看起来会通过检查每个标签来降低性能。我想像下面这样写这个过程。 1. 对通过的标签运行insert or ignore sql。 2. 新建文章实例。 3、给文章实例的.tags添加标签。 4. 刷新新文章到数据库。然后 4,我认为它只会运行 2 个查询。 1. 创建文章 2. 批量创建标签 现在我明白它不能通过附加集合。对不起我糟糕的英语......
猜你喜欢
  • 2018-06-19
  • 1970-01-01
  • 2017-07-07
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
  • 2021-06-20
  • 1970-01-01
相关资源
最近更新 更多