AttributeError: 'unicode'对象没有'_sa_instance_state'属性

9 投票
2 回答
13534 浏览
提问于 2025-04-17 01:21

我正在学习如何使用SQLAlchemy。我想做的是把标题和链接存储在两个不同的表里:

temp = Submissions(title=u'Facebook Homepage', link=u'http://facebook.com')
session.add(temp)
session.flush()
transaction.commit()

通过:

class Links(Base):
    __tablename__ = 'links'
    id = Column(Integer, primary_key=True)
    link = Column(Text)
    created = Column(TIMESTAMP(), default=datetime.now())

    def __init__(self, link):
        self.link = link

class Submissions(Base):
    __tablename__ = 'submissions'
    id = Column(Integer, primary_key=True)
    created = Column(TIMESTAMP(), default=datetime.now())
    title = Column(Text)
    link_id = Column(Integer, ForeignKey('links.id'))
    link = relation(Links)

    def __init__(self, title, link):  
        self.title = title
        self.link = link

但是我总是遇到这个错误:

AttributeError: 'unicode' object has no attribute '_sa_instance_state'

这是怎么回事呢?有没有更好的写法?

2 个回答

2

我会把这个关系设置为一对一uselist=False),并添加一个属性来封装link的关系。这样,SQLAlchemy的配置就会像下面这样,你的代码在创建、更新和删除链接时应该都能正常工作。不过,你可能需要在cascade中配置这个关系,以便使用delete-orphan选项。

...
class Submissions(Base):
    __tablename__ = 'submissions'
    id = Column(Integer, primary_key=True)
    created = Column(DateTime(), default=datetime.now())
    title = Column(Text)
    link_id = Column(Integer, ForeignKey('links.id'))
    link_rel = relation(Links, backref=backref("_submission", uselist=False))

    def __init__(self, title, link=None):
        self.title = title
        self.link = link

    @property
    def link(self):
        return self.link_rel and self.link_rel.link

    @link.setter
    def link(self, value):
        if value is None:
            self.link_rel = None
        elif self.link_rel is None:
            self.link_rel = Links(value)
        else:
            self.link_rel.link = value
...
8

你不能直接用 relationship 来做到这一点。

你需要想办法让 Link 被查找。

最简单的方法就是直接查找它。

submission_link = session.query(Links) \
                         .filter(Links.link == u'http://facebook.com') \
                         .first()
if submission_link is None:
    submission_link = Links(link=u'http://facebook.com')
    session.add(submission_link)

submission = Submissions(title=u'Facebook Homepage', link=submission_link)
session.add(submission)
session.commit()

你也可以使用 混合属性,这样看起来更像你的例子,但其实会复杂很多。

另外,记得用 relationship,因为 relation 已经不推荐使用了。

撰写回答