使用事务插入数据时出现 NoReferencedTableError
NoReferencedTableError while using transaction to insert data
我正在构建一个简单的民意调查网络应用程序,我需要在数据库中插入民意调查,目前民意调查以 JSON 结构表示:
[
{
"title":"Do you like dogs?",
"type":"select",
"options":[
"Yes",
"No"
]
},
{
"title":"What type of dogs do you like?",
"type":"choices",
"options":[
"All",
"None",
"Labrador"
]
},
{
"title":"Why do you like dogs?",
"type":"text"
},
{
"title":"How much do you like dogs?",
"type":"range"
}
]
这是我目前使用的代码:
@polls.route('/create', methods=['POST'])
def pollcreate_post():
data = request.form
r, l, valid = [], None, {'select', 'text', 'range', 'checkbox', 'choices', 'range', 'date'}
options = { 'select', 'checkbox', 'choices'}
for a, b in data.items():
if a in valid:
l = a
r.append({'title':b, 'type':a})
elif a.startswith('option') and l in options:
r[-1]['options'] = [*r[-1].get('options', []), b]
try:
pollname = 'Polls Test Name'
newpoll = Poll(pollname=pollname, polldate=datetime.now())
newpoll.questions = []
db.session.add(newpoll)
for question in r:
questiontype = question['type']
questiontitle = question['title']
questiontypeid = QuestionType.query.filter_by(name=questiontype).first()
categoryid = Category.query.filter_by(name='Animals').first()
newquestion = Question(questiontypeid=questiontypeid.questiontypeid, categoryid=categoryid.categoryid, title = questiontitle, required=False)
newquestion.answers = []
if questiontype in {'select', 'checkbox', 'choices'}:
for qoption in question['options']:
newanswer = Answer(questionid=newquestion.questionid,name=qoption)
newquestion.answers.append(newanswer)
newpoll.questions.append(newquestion)
db.session.commit()
except:
db.session.rollback()
raise
return render_template('poll-create.html')
我不知道为什么,但在接收数据并插入答案时引发了这个异常:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'PollQuestions.questionid' could not find table 'questions' with which to generate a foreign key to target column 'questionid'
在这里你可以找到我的模型:
pollquestions = Table('PollQuestions', Base.metadata,
Column('pollid', Integer, ForeignKey('polls.pollid'), primary_key=True),
Column('questionid', Integer, ForeignKey('questions.questionid'), primary_key=True))
class Poll(db.Model):
__tablename__ = 'polls'
pollid = Column(Integer, primary_key=True)
pollname = Column(String(255))
polldate = Column(Date)
questions = relationship("Question", secondary=pollquestions)
class Question(db.Model):
__tablename__ = 'questions'
questionid = Column(Integer, primary_key=True)
questiontypeid = Column(Integer, ForeignKey('QuestionTypes.questiontypeid'))
categoryid = Column(Integer, ForeignKey('Categories.categoryid'))
title = Column(String(255))
required = Column(Boolean)
polls = relationship("Poll", secondary=pollquestions)
answers = relationship("Answer")
polls = relationship("Poll")
class Answer(db.Model):
__tablename__ = 'answers'
answerid = Column(Integer, primary_key=True)
questionid = Column(Integer, ForeignKey('Questions.questionid'))
name = Column(String(255))
您的 Question
class 显然有一个由数据库自动生成的 questionid
属性。在您创建一个新的 Question
对象后,它的 questionid
属性立即变为 None
。将对象添加到会话不会更改该值,因为到目前为止一切都发生在 SQLAlchemy 端。
如果您需要 questionid
的实际值,您必须执行 db.session.flush()
以将 INSERT 语句发送到数据库并更新 ORM 对象。然后 newquestion.questionid
将不再是 None
,您可以像以前一样创建 Answer
对象。
或者,您可以在 Answers
class 中设置一个 relationship,这样您就可以根据其 对象定义相关的 Question
而不是它的 questionid
值。
我正在构建一个简单的民意调查网络应用程序,我需要在数据库中插入民意调查,目前民意调查以 JSON 结构表示:
[
{
"title":"Do you like dogs?",
"type":"select",
"options":[
"Yes",
"No"
]
},
{
"title":"What type of dogs do you like?",
"type":"choices",
"options":[
"All",
"None",
"Labrador"
]
},
{
"title":"Why do you like dogs?",
"type":"text"
},
{
"title":"How much do you like dogs?",
"type":"range"
}
]
这是我目前使用的代码:
@polls.route('/create', methods=['POST'])
def pollcreate_post():
data = request.form
r, l, valid = [], None, {'select', 'text', 'range', 'checkbox', 'choices', 'range', 'date'}
options = { 'select', 'checkbox', 'choices'}
for a, b in data.items():
if a in valid:
l = a
r.append({'title':b, 'type':a})
elif a.startswith('option') and l in options:
r[-1]['options'] = [*r[-1].get('options', []), b]
try:
pollname = 'Polls Test Name'
newpoll = Poll(pollname=pollname, polldate=datetime.now())
newpoll.questions = []
db.session.add(newpoll)
for question in r:
questiontype = question['type']
questiontitle = question['title']
questiontypeid = QuestionType.query.filter_by(name=questiontype).first()
categoryid = Category.query.filter_by(name='Animals').first()
newquestion = Question(questiontypeid=questiontypeid.questiontypeid, categoryid=categoryid.categoryid, title = questiontitle, required=False)
newquestion.answers = []
if questiontype in {'select', 'checkbox', 'choices'}:
for qoption in question['options']:
newanswer = Answer(questionid=newquestion.questionid,name=qoption)
newquestion.answers.append(newanswer)
newpoll.questions.append(newquestion)
db.session.commit()
except:
db.session.rollback()
raise
return render_template('poll-create.html')
我不知道为什么,但在接收数据并插入答案时引发了这个异常:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'PollQuestions.questionid' could not find table 'questions' with which to generate a foreign key to target column 'questionid'
在这里你可以找到我的模型:
pollquestions = Table('PollQuestions', Base.metadata,
Column('pollid', Integer, ForeignKey('polls.pollid'), primary_key=True),
Column('questionid', Integer, ForeignKey('questions.questionid'), primary_key=True))
class Poll(db.Model):
__tablename__ = 'polls'
pollid = Column(Integer, primary_key=True)
pollname = Column(String(255))
polldate = Column(Date)
questions = relationship("Question", secondary=pollquestions)
class Question(db.Model):
__tablename__ = 'questions'
questionid = Column(Integer, primary_key=True)
questiontypeid = Column(Integer, ForeignKey('QuestionTypes.questiontypeid'))
categoryid = Column(Integer, ForeignKey('Categories.categoryid'))
title = Column(String(255))
required = Column(Boolean)
polls = relationship("Poll", secondary=pollquestions)
answers = relationship("Answer")
polls = relationship("Poll")
class Answer(db.Model):
__tablename__ = 'answers'
answerid = Column(Integer, primary_key=True)
questionid = Column(Integer, ForeignKey('Questions.questionid'))
name = Column(String(255))
您的 Question
class 显然有一个由数据库自动生成的 questionid
属性。在您创建一个新的 Question
对象后,它的 questionid
属性立即变为 None
。将对象添加到会话不会更改该值,因为到目前为止一切都发生在 SQLAlchemy 端。
如果您需要 questionid
的实际值,您必须执行 db.session.flush()
以将 INSERT 语句发送到数据库并更新 ORM 对象。然后 newquestion.questionid
将不再是 None
,您可以像以前一样创建 Answer
对象。
或者,您可以在 Answers
class 中设置一个 relationship,这样您就可以根据其 对象定义相关的 Question
而不是它的 questionid
值。