我需要定义多个包含 SQLAlchemy 声明性类的模块。我在每个模块中编写了一个名为subclass_base()
其中一个 Base 实例declarative_base()
实例化后传递。第一个模块的subclass_base()
正确调用会子类化 Base 实例,并且子类从函数外部可见。第二个模块的调用完成时没有错误,但从函数内部和外部来看,所有子类都反映在Base.__subclasses__
只是某些时候。这是一个最小的工作示例,每个模块中只有 1 个类定义:
模型文件
from sqlalchemy import Column, Integer, String
def subclass_base(Base):
class Roles(Base):
__tablename__ = 'roles'
id = Column(Integer, primary_key=True)
name = Column(String(32))
模型b.py
from sqlalchemy import Column, Integer, String
def subclass_base(Base):
class Locations(Base):
__tablename__ = 'locations'
id = Column(Integer, primary_key=True)
name = Column(String(64))
test.py
from sqlalchemy.ext.declarative import declarative_base
from modela import subclass_base as amod
from modelb import subclass_base as bmod
def test():
count = 0
while True:
try:
Base = declarative_base()
amod(Base)
bmod(Base)
sc = [subclass.__name__ for subclass in Base.__subclasses__()]
assert(len(sc) == 2)
print('.', end='')
count += 1
except AssertionError:
print("Failed after {} successful pass(es)".format(count))
count = 0
我怀疑这个问题是我忽略了 declarative_base() 进行的元类工作的一个特定问题,但我似乎无法弄清楚发生了什么。我也想知道这是否是一个继承问题。我是否应该采取不同的架构方法,而不是使用函数来子类化单个基类?
不要在函数内定义类。只需定义Base
在单个定义模块中,然后从其他模块导入该模块:
db.py
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
Session = sessionmaker()
def bind_engine(engine):
Base.metadata.bind = engine
Session.configure(bind=engine)
模型文件
from sqlalchemy import Column, Integer, String
from db import Base
class Roles(Base):
__tablename__ = 'roles'
id = Column(Integer, primary_key=True)
name = Column(String(32))
模型b.py
from sqlalchemy import Column, Integer, String
from db import Base
class Locations(Base):
__tablename__ = 'locations'
id = Column(Integer, primary_key=True)
name = Column(String(64))
用户脚本.py
from sqlalchemy import create_engine
engine = create_engine('postgresql://user:pwd@server/database')
from yourproject.db import bind_engine
bind_engine(engine)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)