繁体   English   中英

如何在SQLAlchemy 1.2.7中创建没有定义类的新表

[英]How to Create New Tables without Defined Classes in SQLAlchemy 1.2.7

我正在使用SQLAlchemy的声明性API为应用程序构建模型和表。

但是,由于错误NoReferencedTableError: Foreign key associated with column 'org_prediction.company_id' could not find table 'organization' with which to generate a foreign key to target column 'id' ,我无法使用Base.metadata.create_all(engine)命令在数据库中构建新表NoReferencedTableError: Foreign key associated with column 'org_prediction.company_id' could not find table 'organization' with which to generate a foreign key to target column 'id'

发生这种情况的原因是因为我要为ForeignKey引用的组织类在我的models.py文件中不存在。 因此,当我调用Base.metadata.create_all(engine) ,SQLAlchemy阻塞了,因为Base中不存在Organization类。

我尝试反映我的数据库,该数据库将返回存在的组织表,但在我的models.py文件中没有为其编写相应的类。 但是,当我反映数据库表并尝试在Organization顶部创建我的新依赖类时,出现类似以下错误: InvalidRequestError: Table 'user' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object. InvalidRequestError: Table 'user' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object. ,这是由于反射的MetaData和我的User的models.py类重叠,并且SQLAlchemy不确定该怎么做。

但是我应该在哪里应用extend_existing = True? 我没有要将此参数传递给的表对象。 当我的FK依赖表不存在于models.py文件中时,如何创建我的FK依赖表? 或者如何反映现有表,但仅追加或更新数据库中尚不存在的类?

models.py

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    username = Column(String(50))

class OrgPrediction(Base):
    __tablename__ = 'org_prediction'
    id = Column(Integer, primary_key=True)
    company_id = Column(String(255), ForeignKey('organization.id'), nullable=True)
    prediction = Column(String(255)
Base.metadata.create_all(engine)

NoReferencedTableError:与列“ org_prediction.company_id”关联的外键找不到表“ organization”,通过该表可生成目标列“ id”的外键

MYSQL:

mysql> desc organization;
+-----------------------+------------+------+-----+---------+-------+
| Field                 | Type       | Null | Key | Default | Extra |
+-----------------------+------------+------+-----+---------+-------+
| id                 | bigint(20) | YES  | MUL | NULL    |       |


mysql> show tables;
+-------------------------+
| Tables_in_database |
+-------------------------+
| organization            |
| user                    |
| user_email              |

如果是反射,则使用models.py文件:

from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine

Base = automap_base()
Base.prepare(engine, reflect=True)

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    username = Column(String(50))

class OrgPrediction(Base):
    __tablename__ = 'org_prediction'
    id = Column(Integer, primary_key=True)
    company_id = Column(String(255), ForeignKey('organization.id'), nullable=True)

Base.metadata.create_all(engine)

InvalidRequestError:已为此MetaData实例定义表'user'。 指定“ extend_existing = True”以重新定义现有Table对象上的选项和列。

有一种方法可以做到这一点,它涉及在添加外键依赖表之前使用Base.metadata.reflect(only = ['table_name'])功能。 我测试的最终代码:

Base = declarative_base()
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    username = Column(String(50))

#see what tables exist in metadata right now
In [85]: Base.metadata.sorted_tables
Out[85]: [Table('user', MetaData(bind=None), Column('id', Integer(), table=<user>, primary_key=True, nullable=False), Column('username', String(length=50), table=<user>), schema=None)]

# this will add the organization table/class to the Base's Metadata. This also needs to happen before the Foreign Key reference in OrgPrediction class.
Base.metadata.reflect(bind=engine, only=['organization'])

# now this class' foreign key will reference organization.id which exists in Base metadata.
class OrgPrediction(Base):
    __tablename__ = 'org_prediction'
    id = Column(Integer, primary_key=True)
    company_id = Column(String(255), ForeignKey('organization.id'), nullable=True)
    prediction = Column(String(255))

# this should pass because the foreign key constraint is met.
Base.metadata.create_all(engine)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM