在表存在之前,如何用flask-sqlalchemy映射表关系?

0 人关注

我在flask-sqlalchemy中创建表之间的关系时遇到一个问题。我有一个项目概览表,从那里开始,我想动态地创建与项目概览有关系的新实验表。然而,当我试图定义这种关系时,sqlalchemy抛出了以下错误。

sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Projects->projects, expression 'Experiment_Overview' failed to locate a name ('Experiment_Overview'). If this is a c
lass name, consider adding this relationship() to the <class 'app.Projects'> class after both dependent classes have been defined.

这似乎是由于Experiment_Overview(db.Model)类不存在。yet,这是正确的,因为它将在以后通过用户输入而动态生成。我怎样才能减轻这个错误?

import os
from flask import Flask, render_template, redirect, request, url_for
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
Bootstrap(app)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///DATA/DB.db"
db = SQLAlchemy(app)
def TableCreator(tablename):
  class Experiment_Overview(db.Model):
    __tablename__ = tablename
    creation_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    experiment_name = db.Column(db.String(30), unique=False, nullable=False, primary_key=True)
    projectname = db.Column(db.String(150), db.ForeignKey('projects.projectname'), nullable=False, unique=True)
  return MyTable
class Projects(db.Model):
    projectname = db.Column(db.String(150), unique=True, nullable=False, primary_key=True)
    creation_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    experiments = db.relationship('Experiment_Overview', backref="experiments", lazy=True, uselist=False)
    def __init__(self, owner, projectname, status, created_at):
        self.owner=owner
        self.projectname=projectname
        self.status=status
        self.created_at=created_at
db.create_all()
    
python
sqlite
flask
sqlalchemy
flask-sqlalchemy
Rivered
Rivered
发布于 2022-05-18
1 个回答
Expanding-Dev
Expanding-Dev
发布于 2022-06-11
已采纳
0 人赞同

一般说来 ,你不会动态地创建表;你通常不应该在你的程序运行时创建或删除表。
此外,我相信不可能创建一个真正的关系,链接到整个表。关系/外键是为 linking between rows 在表格中。

不要担心,在这里有更简单的方法来实现你所寻找的行为。

从你的问题来看,你可以有多个项目,而每个项目可以在项目中拥有多个实验。
这将使一个项目和它的实验之间的关系成为一种 一对多的关系 .

如果是这样的话,你就需要一个Projects表(你的代码中已经有了),你还需要一个Experiments表。

项目表中的每一行代表一个项目。 在Experiments表中的每一行代表一个Experiment。实验表将有一列包含一个外键,链接到实验所链接的项目。

我根据我上面链接的SQLAlchemy文档中给出的One-To-Many示例代码修改了你的代码。 注意在 relationship() 的基础上增加了 back_populates 选项,这允许双向了解关系:实验知道它属于哪个项目,而项目知道它有哪些实验。

import os
from flask import Flask, render_template, redirect, request, url_for
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
Bootstrap(app)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///DATA/DB.db"
db = SQLAlchemy(app)
class Projects(db.Model):
    __tablename__ = "projects"
    projectname = db.Column(db.String(150), unique=True, nullable=False, primary_key=True)
    creation_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    experiments = db.relationship("Experiment", back_populates="project")
    def __init__(self, owner, projectname, status, created_at):
        self.owner=owner
        self.projectname=projectname
        self.status=status
        self.created_at=created_at
class Experiment(db.Model):
    __tablename__ = "experiments"
    creation_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    experiment_name = db.Column(db.String(30), unique=False, nullable=False, primary_key=True)