我正在试图弄清楚如何将SQLAlchemy类分布在几个文件中,而我可以为生活找不到如何做到这一点。我对SQLAlchemy很新,所以如果这个问题很简单,请原谅我。
在中考虑这三个类,每个类都有自己的文件:
A.py:
from sqlalchemy import *
from main import Base
class A(Base):
__tablename__ = "A"
id = Column(Integer, primary_key=True)
Bs = relationship("B", backref="A.id")
Cs = relationship("C", backref="A.id")
B.py:
from sqlalchemy import *
from main import Base
class B(Base):
__tablename__ = "B"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
C.py:
from sqlalchemy import *
from main import Base
class C(Base):
__tablename__ = "C"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
然后说我们有 main.py 这样的东西:
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker
Base = declarative_base()
import A
import B
import C
engine = create_engine("sqlite:///test.db")
Base.metadata.create_all(engine, checkfirst=True)
Session = sessionmaker(bind=engine)
session = Session()
a = A.A()
b1 = B.B()
b2 = B.B()
c1 = C.C()
c2 = C.C()
a.Bs.append(b1)
a.Bs.append(b2)
a.Cs.append(c1)
a.Cs.append(c2)
session.add(a)
session.commit()
上面给出了错误:
sqlalchemy.exc.NoReferencedTableError: Foreign key assocated with column 'C.A_id' could not find table 'A' with which to generate a foreign key to target column 'id'
如何跨这些文件共享声明基础?
实现这一目标的“正确”方法是什么,考虑到我可能会抛出像 Pylons 或 Turbogears 这样的东西?
编辑10-03-2011
我从金字塔框架中找到了描述问题的this描述,更重要的是验证这是一个实际问题,而不是(仅)我困惑的自我就是问题。希望它可以帮助那些敢于走这条危险道路的人:)
答案 0 :(得分:67)
解决问题的最简单方法是将Base
从导入A
,B
和C
的模块中取出;打破循环导入。
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy import *
from base import Base
from sqlalchemy.orm import relationship
class A(Base):
__tablename__ = "A"
id = Column(Integer, primary_key=True)
Bs = relationship("B", backref="A.id")
Cs = relationship("C", backref="A.id")
from sqlalchemy import *
from base import Base
class B(Base):
__tablename__ = "B"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
from sqlalchemy import *
from base import Base
class C(Base):
__tablename__ = "C"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
from sqlalchemy import create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker
import base
import a
import b
import c
engine = create_engine("sqlite:///:memory:")
base.Base.metadata.create_all(engine, checkfirst=True)
Session = sessionmaker(bind=engine)
session = Session()
a1 = a.A()
b1 = b.B()
b2 = b.B()
c1 = c.C()
c2 = c.C()
a1.Bs.append(b1)
a1.Bs.append(b2)
a1.Cs.append(c1)
a1.Cs.append(c2)
session.add(a1)
session.commit()
在我的机器上运行:
$ python main.py ; echo $?
0
答案 1 :(得分:8)
我正在使用Python 2.7 + Flask 0.10 + SQLAlchemy 1.0.8 + Postgres 9.4.4.1
此样板配置了User和UserDetail模型,这些模型存储在“user”模块的同一文件“models.py”中。这些类都继承自SQLAlchemy基类。
我添加到项目中的所有其他类也派生自此基类,并且随着models.py文件变大,我决定将models.py文件拆分为每个类的一个文件,然后遇到这里描述的问题。
我找到的解决方案与@ computermacgyver 2013年10月23日发布的内容一样,是将我的所有类都包含在我创建的新模块的 init .py文件中以保存所有新的创建了类文件。看起来像这样:
/project/models/
__init__.py contains
from project.models.a import A
from project.models.b import B
etc...
答案 2 :(得分:0)
对我来说,在import app.tool.tool_entity
内添加app.py
并在from app.tool.tool_entity import Tool
内添加tool/__init__.py
足以创建表。不过,我还没有尝试添加关系。
文件夹结构:
app/
app.py
tool/
__init__.py
tool_entity.py
tool_routes.py
# app/tool/tool_entity.py
from app.base import Base
from sqlalchemy import Column, Integer, String
class Tool(Base):
__tablename__ = 'tool'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
fullname = Column(String)
fullname2 = Column(String)
nickname = Column(String)
def __repr__(self):
return "<User(name='%s', fullname='%s', nickname='%s')>" % (
self.name, self.fullname, self.nickname)
# app/tool/__init__.py
from app.tool.tool_entity import Tool
# app/app.py
from flask import Flask
from sqlalchemy import create_engine
from app.tool.tool_routes import tool_blueprint
from app.base import Base
db_dialect = 'postgresql'
db_user = 'postgres'
db_pwd = 'postgrespwd'
db_host = 'db'
db_name = 'db_name'
engine = create_engine(f'{db_dialect}://{db_user}:{db_pwd}@{db_host}/{db_name}', echo=True)
Base.metadata.create_all(engine)
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
app.register_blueprint(tool_blueprint, url_prefix='/tool')
if __name__ == '__main__':
# you can add this import here, or anywhere else in the file, as debug (watch mode) is on,
# the table should be created as soon as you save this file.
import app.tool.tool_entity
app.run(host='0.0.0.0', port=5000, debug=True)