Estoy tratando de averiguar cómo han SQLAlchemy clases repartidos en varios archivos, y puedo por mi vida, no averiguar cómo hacerlo. Soy bastante nuevo para SQLAlchemy así que me perdone si esta pregunta es trivial..

Considerar estas 3 clases en cada uno su propio archivo de:

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 dicen 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  = 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()

El de arriba te 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 puedo compartir declarativo de base a través de estos archivos?

¿Qué es el «derecho» de manera de lograr esto, teniendo en cuenta que yo podría lanzar algo como Torres o Turbogears en la parte superior de esto?

editar 10-03-2011

He encontrado este descripción de las Pirámides marco que describe el problema y lo que es más importante verifica que este es un problema real y no (sólo) solo mi confundido yo que es el problema. Espero que pueda ayudar a otros que se atreve abajo de este peligroso camino 🙂

  • ¿Qué parte de la Python import declaración confunde usted?
  • Lo anterior funciona si todas las clases son en un solo archivo, por lo que me dices 🙂
  • El código no da este error, por favor enviar el código que tiene el error real. Arreglar sus importaciones, hacer que se ejecute lo que alguien puede realmente ver su error.
  • «¿Cómo puedo compartir declarativo de base a través de estos archivos?» De nuevo, voy a preguntar. «¿Qué parte de la Python import declaración confunde usted?» Se puede proporcionar una pregunta específica sobre por qué import no está funcionando? Puede usted proporcionar razones específicas por las que import no está funcionando? O tenemos que adivinar lo que confunde a usted acerca de import? El «dime» es imposible. No sabemos lo que confunde. Por favor, nos dan una pista.
  • Mi confusión era aparentemente centrada en torno a cómo evitar cíclico de las importaciones. Yo vengo de C donde esto no es un problema. Mis disculpas por tomar su tiempo.
  • Qué? ¿Cuáles son estos cíclico importar los problemas que está teniendo. Por favor enviar el código con el ciclo de las importaciones para que podamos explicar cómo se descompone ellos y evitar los ciclos. Hay demasiados vagos casos hipotéticos en estos comentarios. ¿Qué problema tiene usted? Por favor, sea específico.

InformationsquelleAutor joveha | 2011-09-19

4 Comentarios

  1. 74

    La solución más simple para el problema va a ser para tomar Base fuera del módulo que importa A, B y C; Romper el ciclo de importación.

    base.py

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

    una.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 = 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()

    Funciona en mi máquina:

    $ python main.py ; echo $?
    0
    • Uso scoped_session.
    • manejo de sesiones no está relacionado con la pregunta en este post, que en realidad es un viejo y simple de python pregunta (¿cómo puedo importar cosas?); pero desde que tengo su atención, les aconsejo a los fuertemente contra el uso de scoped_session, a menos que usted sepa por qué usted necesita el almacenamiento local de subprocesos; El problema con el uso de scoped_session es que hace que sea fácil de viento con filtró las transacciones y datos obsoletos, sin vínculo explícito con el punto en el código al que podría haber ocurrido.
    • Este patrón de diseño no parece funcionar para python3. ¿Hay alguna solución fácil que es python3 compatible?
    • este patrón debería funcionar correctamente a través de las versiones de python. Por favor, hacer una nueva pregunta, de modo que usted puede incluir la totalidad de su el código, y los errores que usted está viendo.
    • Gracias @dequestarmappartialsetattr . He encontrado el error sólo ocurre cuando traté de poner una.py, b.py,. c.py, y model.py en un módulo independiente. He encontrado la solución en este caso fue la de incluir la base.py código en el módulo del __init__.py archivo en su lugar. He puesto la de código y una explicación más detallada aquí. Gracias por la respuesta.
  2. 8

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

    Este repetitivo viene configurado con un Usuario y UserDetail modelos almacenados en el mismo archivo «models.py» en el «usuario» del módulo. Estas clases heredan de una SQLAlchemy de la clase base.

    Todas las clases adicionales, he añadido a mi proyecto, también se deriva de esta clase base, y como el models.py archivo creció más, he decidido dividir el models.py archivo en un archivo por cada clase, y se topó con el problema que se describe aquí.

    La solución que he encontrado, a lo largo de las mismas líneas que @computermacgyver del 23 Oct 2013 post, era para incluir a todas mis clases a la init.py archivo del módulo nuevo que he creado para contener todos los recién creado los archivos de clase. Se parece a esto:

    /project/models/
    
    __init__.py contains
    
    from project.models.a import A 
    from project.models.b import B
    etc...
    • ¿por qué usted piensa que necesita usar el Frasco?
  3. 7

    Si me pueden agregar mi poco de sentido así desde que yo tenía el mismo problema. Usted necesita para importar las clases en el archivo donde se crea el Base = declarative_base() DESPUÉS de crear la Base y la Tables. Breve ejemplo de cómo mi proyecto es establecer:

    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
  4. 0

    Para mí, la adición de import app.tool.tool_entity dentro de app.py y from app.tool.tool_entity import Tool dentro de tool/__init__.py fue suficiente para obtener la tabla a crear. No he probado la adición relación, sin embargo, a pesar de que.

    Estructura de carpetas:

    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)

Dejar respuesta

Please enter your comment!
Please enter your name here