为什么SQLAlchemy / associationproxy复制我的标签?

问题描述 投票:4回答:3

在与the example in the docs非常相似的情况下,我正在尝试对标签使用关联代理。这是我的模式的子集(这是一个博客),使用声明式:

class Tag(Base):
    __tablename__ = 'tags'
    id            = Column(Integer, primary_key=True)
    tag           = Column(Unicode(255), unique=True, nullable=False)

class EntryTag(Base):
    __tablename__ = 'entrytags'
    entry_id      = Column(Integer, ForeignKey('entries.id'), key='entry', primary_key=True)
    tag_id        = Column(Integer, ForeignKey('tags.id'), key='tag', primary_key=True)

class Entry(Base):
    __tablename__ = 'entries'
    id            = Column(Integer, primary_key=True)
    subject       = Column(Unicode(255), nullable=False)
    # some other fields here
    _tags         = relation('Tag', backref='entries', secondary=EntryTag.__table__)
    tags          = association_proxy('_tags','tag')

这是我尝试使用的方式:

>>> e = db.query(Entry).first()
>>> e.tags
[u'foo']
>>> e.tags = [u'foo', u'bar']  # really this is from a comma-separated input
db.commit()
Traceback (most recent call last):
[...]
sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "tags_tag_key"
 'INSERT INTO tags (id, tag) VALUES (%(id)s, %(tag)s)' {'tag': 'bar', 'id': 11L}
>>> map(lambda t:(t.id,t.tag), db.query(Tag).all())
[(1, u'foo'), (2, u'bar'), (3, u'baz')]

标签u'bar'已存在,ID为2;为什么SQLAlchemy不只是附加那个而不是尝试创建它?我的架构是否有误?

python orm tags sqlalchemy declarative
3个回答
3
投票

免责声明:自从我使用SQLAlchemy以来已经有很多年了,所以这比任何事情都更容易让人猜测。

似乎您期望SQLAlchemy在多对多表上执行插入操作时神奇地采用字符串'bar'并为其查找相关的Tag。我认为这是无效的,因为所讨论的字段(“标记”)不是主键。

想象一下类似的情况,其中您的Tag表实际上是Comment,也带有id和文本字段。您希望能够使用与上面使用的相同的e.comments = ['u'Foo','u'Bar']语法将注释添加到条目,但您希望它仅执行插入,不检查内容相同的现有注释。

所以这可能就是它在这里所做的,但是它会在标签名称上遇到唯一性约束并失败,并假设您尝试做错事。

如何解决?将tag.tag作为主键可以说是正确的做法,尽管我不知道SQLAlchemy的效率和效率。失败的话,请尝试按名称查询Tag对象,然后再将其分配给条目。您可能需要编写一个小的实用程序函数,该函数需要一个unicode字符串并返回一个现有Tag或为您创建一个新Tag。


0
投票

我还从未使用过SQLAlchemy 0.5(我使用的最后一个应用程序是基于0.4的,但是我可以在您的代码中看到一个怪癖:您应该modify association_proxy对象,而不是重新分配它。

尝试做类似的事情:

e.tags.append(u"bar")

代替

e.tags = ...

如果这不起作用,请尝试为这些表粘贴一个完整的工作示例(请输入),我会给您更多建议。


0
投票

Kylotan's answer中的FAQ URL为moved to hereUniqueObject recipe仍在同一位置。

这将是对该分析器的评论,但是由于SO的智慧水平,我不允许发表评论。

© www.soinside.com 2019 - 2024. All rights reserved.