【问题标题】:How to insert the 'answer' model?如何插入“答案”模型?
【发布时间】:2011-04-09 16:16:37
【问题描述】:

标题可能不准确,但我不知道如何表达。

我有 3 个类:用户、问题、答案。简单的代码是:

Session = scoped_session(sessionmaker())
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)

    questions = relationship('Question', backref="user")
    answers = relationship('Answer', backref="user")

class Question(Base):
     __tablename__ = 'questions'
     id = Column(Integer, primary_key=True)
     user_id = Column(Integer, ForeignKey('users.id'))

     answers = relationship('Answer', backref="user")

class Answer(Base):
     __tablename__ = 'answers'
     user_id = Column(Integer, ForeignKey('users.id'))
     question_id = Column(Integer, ForeignKey('questions.id'))

     id = Column(Integer, primary_key=True)

现在,一位用户提出了一个问题,因此将创建一个答案:

user = get_user_from_session()
question = get_question(question_id)

# create answer
answer = Answer()
answer.user = user
answer.question = question

Session.add(answer)  # !!!
Session.commit()

希望将答案插入数据库,可惜报错:

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

有什么我错过的吗?如何解决?


更新

感谢@dhaffey,我已修正错别字。我重新创建了一个测试文件进行测试,发现没有再次发生错误,但是提交后answer.user_idanswer.question_id在数据库中为空。

这是我的代码,你可以直接运行。

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import *

engine = create_engine('sqlite:///test.sqlite', echo=True)
Session = scoped_session(sessionmaker())
Base = declarative_base()

Base.metadata.bind=engine

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    questions = relationship('Question')
    answers = relationship('Answer')

class Question(Base):
    __tablename__ = 'questions'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    title = Column(String)
    answers = relationship('Answer')

class Answer(Base):
    __tablename__ = 'answers'
    user_id = Column(Integer, ForeignKey('users.id'))
    question_id = Column(Integer, ForeignKey('questions.id'))

    id = Column(Integer, primary_key=True)

Base.metadata.create_all()

user = User()
user.name = 'aaa'
Session.add(user)
Session.flush()

question = Question()
question.title = 'ttt'
question.user = user
Session.add(question)
Session.flush()

answer = Answer()
answer.user = user
answer.question = question

Session.add(answer)
Session.commit()

print answer.id # not None

found = Session.query(Answer).filter_by(id=answer.id).one()

print found.user.name # not None
print found.question.title # not None

# !!! It seems all models are saved correctly,
# but please open the test.sqlite database, (not querying by sqlahchemy)
# the question.user_id and answer.user_id and answer.question_id are null

【问题讨论】:

    标签: sqlalchemy relationship


    【解决方案1】:

    你的类声明不会为我“编译”,所以我想知道你是否运行过这段代码,如果是的话,你使用的是哪个 SQLAlchemy 版本。线

    user_id = Column(Integer, ForeignKey='users.id')
    

    加注

    sqlalchemy.exc.ArgumentError: Unknown arguments passed to Column: ['ForeignKey']
    

    使用 SQLAlchemy 0.6.4。您正在尝试使用关键字参数声明外键,但正确的用法是构造一个 ForeignKey 对象并按位置传递它,如下所示:

    user_id = Column(Integer, ForeignKey('users.id'))
    

    固定外键后,您的示例按预期工作。

    请注意,当相应的外键被适当声明时,您不需要在这些关系上显式提供 primaryjoin 参数 - SQLAlchemy 会推断出正确的连接。

    【讨论】:

    • 对不起,ForeignKey 的错误是一个错字(我是手写的代码,不是复制的)。我刚刚修复它并再次尝试,这次没有发现错误(可能示例代码比实际的要容易得多),但是answer.user_idanswer.question_id在数据库中为空。所以,answer.user = useranswer.question = question 实际上什么也没做。你能再次运行你的测试并检查一下吗?
    • 当您修复其他拼写错误时,您通过删除某些关系的 backref 参数引入了一个新错误。没有这些,userquestion 属性只是没有数据库支持的常规 Python 属性。通过立即查询将它们取回的原因是 SQLAlchemy 从其身份映射中返回相同的实例(具有相同的瞬态 Python 状态)。为User.questionsUser.answers 指定backref='user',为Question.answers 指定backref='question' 会将它们重新转换为数据库支持的属性。
    • 非常抱歉,这是一个新的错字。更新的代码是我测试时使用的。同样的错误:数据库中的数据没有user_idquestion_id
    • 看起来现在您已经使用 backref 参数更新了代码的原始版本,但我认为您可能仍在测试您的问题中没有的代码他们。如果我使用第一组类定义,user = User() 行会引发异常,因为您为Question.answers 粘贴了backref="user",而不是backref="question"。如果我解决这个问题并运行你的测试,一切都会按预期在数据库中结束。
    猜你喜欢
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多