Классы SQLAlchemy в разных файлах
Я пытаюсь выяснить, как классы SQLAlchemy распространяются по нескольким файлам, и я могу за свою жизнь не понять, как это сделать. Я довольно новичок в SQLAlchemy, поэтому простите меня, если этот вопрос тривиален..
рассмотрим эти 3 класса в каждый свой файл:
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'
как я могу разделить декларативную базу между этими файлами?
каков "правильный" способ сделать это, учитывая, что я могу бросить что-то вроде пилонов или Turbogears на вершине этого?
изменить 10-03-2011
нашел этой описание от пирамиды рамки, которая описывает проблему и что более важно проверка что это реальная проблема, а не (только) просто мое смущенное я, вот в чем проблема. Надеюсь, что это может помочь другим, кто осмеливается вниз по этой опасной дороге:)
3 ответа:
самым простым решением вашей проблемы будет взять
Base
из модуля, который импортируетA
,B
иC
; прервать циклический импорт.base.py
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"))
main.py
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
Я использую Python 2.7 + колба 0.10 + SQLAlchemy 1.0.8 + Postgres 9.4.4.1
этот шаблон поставляется с настроенными моделями User и UserDetail, хранящимися в одном файле "models.py" в модуле "пользователь". Оба эти класса наследуются от базового класса SQLAlchemy.
все дополнительные классы, которые я добавил в свой проект, также являются производными от этого базового класса, и как models.py файл стал больше, я решил разделить models.py файл в один файл для каждого класса, и столкнулся с проблемой, описанной здесь.
решение, которое я нашел, по тем же строкам, что и сообщение @computermacgyver от 23 октября 2013 года, должно было включать все мои классы в файл init.py нового модуля, который я создал для хранения всех вновь созданных файлов классов. Выглядит так:
/project/models/ __init__.py contains from project.models.a import A from project.models.b import B etc...
если я могу добавить немного смысла, так как у меня была та же проблема. Вам нужно импортировать классы в файл, где вы создаете
Base = declarative_base()
после того, как вы создалиBase
иTables
. Короткий пример того, как мой проект настроен:model/user.py
from sqlalchemy import * from sqlalchemy.orm import relationship from model import Base class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) budgets = relationship('Budget')
model/budget.py
from sqlalchemy import * from model import Base class Budget(Base): __tablename__ = 'budget' id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('user.id'))
model/__init__.py
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker _DB_URI = 'sqlite:///:memory:' engine = create_engine(_DB_URI) Base = declarative_base() Base.metadata.create_all(engine) DBSession = sessionmaker(bind=engine) session = DBSession() from .user import User from .budget import Budget