使用事务插入数据时出现 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 值。