Clases de SQLAlchemy a través de archivos

Estoy tratando de averiguar cómo hacer que las clases de SQLAlchemy se distribuyan en varios archivos, y puedo, por mi vida, no descubrir cómo hacerlo. Soy bastante nuevo en SQLAlchemy, así que perdóname si esta pregunta es trivial.

Considere estas 3 clases en cada uno de sus propios archivos :

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")) 

Y luego digamos que tenemos un main.py algo como esto:

 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 = AA() b1 = BB() b2 = BB() c1 = CC() c2 = CC() a.Bs.append(b1) a.Bs.append(b2) a.Cs.append(c1) a.Cs.append(c2) session.add(a) session.commit() 

Lo anterior da el error:

 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' 

¿Cómo comparto la base declarativa en estos archivos?

¿Cuál es la manera “correcta” de lograr esto, considerando que puedo lanzar algo como Pylons o Turbogears sobre esto?

editar 10-03-2011

Encontré esta descripción del marco de Pyramids que describe el problema y, lo que es más importante, verifica que se trata de un problema real y no (solo) solo mi yo confundido es el problema. Espero que pueda ayudar a otros que se atreven por este camino peligroso 🙂

La solución más sencilla a su problema será sacar la Base del módulo que importa A , B y C ; Romper la importación cíclica.

base.py

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

a.py

 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") 

b.py

 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")) 

c.py

 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 = aA() b1 = bB() b2 = bB() c1 = cC() c2 = cC() a1.Bs.append(b1) a1.Bs.append(b2) a1.Cs.append(c1) a1.Cs.append(c2) session.add(a1) session.commit() 

Funciona en mi máquina:

 $ python main.py ; echo $? 0 

Estoy usando Python 2.7 + Flask 0.10 + SQLAlchemy 1.0.8 + Postgres 9.4.4.1

Esta placa de referencia viene configurada con los modelos User y UserDetail almacenados en el mismo archivo “models.py” en el módulo “user”. Estas dos clases heredan de una clase base SQLAlchemy.

Todas las clases adicionales que he agregado a mi proyecto también se derivaron de esta clase base, y a medida que el archivo models.py se hizo más grande, decidí dividir el archivo models.py en un archivo por clase, y encontré el problema descrito aquí.

La solución que encontré, en la misma línea que la publicación de @ computermacgyver del 23 de octubre de 2013, fue incluir todas mis clases en el archivo .py de inicio del nuevo módulo que creé para contener todos los archivos de clase recién creados. Se ve como esto:

 /project/models/ __init__.py contains from project.models.a import A from project.models.b import B etc... 

Si puedo agregar mi poco de sentido también, ya que tuve el mismo problema. Debe importar las clases en el archivo donde crea la Base = declarative_base() DESPUÉS de crear la Base y las Tables . Breve ejemplo de cómo se configura mi proyecto:

modelo / usuario.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') 

modelo / presupuesto.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