This source详细说明如何使用关联代理创建具有ORM对象值的 View 和对象。

但是,当我附加一个与数据库中现有对象匹配的值(并且所述值是唯一键或主键)时,它将创建一个冲突对象,因此我无法提交。

因此,就我而言,这仅用作 View ,并且我将需要使用ORM查询来检索要附加的对象。

这是我唯一的选择还是我可以使用合并(如果它是主键而不是唯一约束,则只能执行合并操作),或者设置构造函数,使其将使用数据库中的现有对象(如果存在)而不是创建一个新对象?

例如从文档:

user.keywords.append('cheese inspector')

# Is translated by the association proxy into the operation:

user.kw.append(Keyword('cheese inspector'))

但是我想翻译成更多类似的东西:(当然,查询可能会失败)。
keyword = session.query(Keyword).filter(Keyword.keyword == 'cheese inspector').one()
user.kw.append(keyword)

或理想情况下
user.kw.append(Keyword('cheese inspector'))
session.merge() # retrieves identical object from the database, or keeps new one
session.commit() # success!

我想这可能不是一个好主意,但是在某些用例中可能是这样的:)

最佳答案

链接到文档页面上显示的示例是关系的composition类型(以OOP术语表示),因此代表了关系的owns类型,而不是动词形式的uses。因此,每个owner将具有相同关键字(在值方面)的自己的副本。

实际上,您可以使用问题中链接到的文档中的建议来创建自定义的creator方法,并对其进行修改以针对给定的 key 重复使用现有对象,而不仅仅是创建一个新的方法。在这种情况下,User类和creator函数的示例代码如下所示:

def _keyword_find_or_create(kw):
    keyword = Keyword.query.filter_by(keyword=kw).first()
    if not(keyword):
        keyword = Keyword(keyword=kw)
        # if aufoflush=False used in the session, then uncomment below
        #session.add(keyword)
        #session.flush()
    return keyword

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    kw = relationship("Keyword", secondary=lambda: userkeywords_table)
    keywords = association_proxy('kw', 'keyword',
            creator=_keyword_find_or_create, # @note: this is the
            )

关于sqlalchemy - 关联代理SQLAlchemy,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9674166/

10-09 16:45