2011-11-17 20 views
12

Actualmente estoy comenzando con sqlalchemy. En mi proyecto actual, tengo que hacer una parte con Flask y otra parte desde la línea de comandos. La parte sobre el matraz se ejecuta correctamente, interconectando con sqlalchemy y todo, pero la parte de la línea de comandos no lo está.SQLAlchemy espera un objeto, pero encuentra una tabla

El error que estoy recibiendo es

ArgumentError("Class object expected, got 'Table('documentos', 
MetaData(bind=Engine(postgresql://user:[email protected]/clasificador)), 
Column('id', Integer(), table=<documentos>, primary_key=True, nullable=False), 
Column('nombre', String(length=248), table=<documentos>), schema=None)'.",) 

He probado suerte con Google y la lectura sqlalchemy declarativa, pero no puedo encontrar lo que podría ser el problema. El código en el módulo es:

from sqlalchemy.orm import sessionmaker 
from db import engine,Base 
#some other code 
session = sessionmaker(bind=engine) 
doc = modelos.documento.Documento(os.path.basename(nelto)) 
session.add(doc) #here fails 
session.remove() 

db es el módulo en el que tengo el código común para sqlalchemy. la mayor parte proviene de la documentación del matraz, y db_session se usa solo para el matraz, hice una sesión diferente para el otro módulo.

from sqlalchemy import create_engine 
from sqlalchemy.orm import scoped_session, sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 

sqldebug=True 

engine = create_engine( 
    'postgresql://user:[email protected]/clasificador', 
    convert_unicode=True, 
    echo=sqldebug) 
db_session = scoped_session(sessionmaker(autocommit=False, 
            autoflush=False, 
            bind=engine)) 
Base = declarative_base(bind=engine) 
Base.query = db_session.query_property() 

Finalmente, aquí está el módulo "documento", aunque dudo que el problema esté aquí. de la Columna de importación sqlalchemy, entero, cadena de db Base importación

class Documento(Base): 
    '''Clase definiendo los documentos''' 
    __tablename__ = "documentos" 

    id = Column(Integer,primary_key=True) 
    nombre = Column(String(248)) 

    def __init__(self,nombre): 
     self.nombre = nombre    

    def __repr__(self): 
     return '<Documento %r>' % self.nombre 

Algunos de los comentarios/nombres están en español, pero creo que se puede ignorar de forma segura, si es necesario, voy a hacer las traducciones

siguiente código de Lafada he creado otro archivo con sólo:

from sqlalchemy.orm import sessionmaker 
from modelos.documento import Documento 
from db import Base, engine 
import os 

Session = sessionmaker(bind=engine) 
session = Session() 
doc = Documento(os.path.basename('/tmp/test.py')) #here fails 
session.add(doc) 
session.commit() 

y funciona muy bien. La única diferencia que puedo detectar es cómo se crea la sesión, la he modificado también en mi código original, pero sigue recibiendo el mismo error.

Encontré el culpable, no estaba en el código que estoy mostrando, pero en una clase diferente que estaba tratando de crear una relación con él pero vinculándose a la mesa en lugar del objeto. Hasta que probé varias otras cosas, no pude encontrar el verdadero problema

Respuesta

6

Probé el código de MySQL (no tengo Postgress en mi pc :(). Estoy poniendo el código aquí Por favor, compruebe que, debido a que está trabajando muy bien para mí.

#filename: /tmp/test.py 
from sqlalchemy import create_engine, Column, Integer, String 
from sqlalchemy.orm import scoped_session, sessio 

nmaker 
from sqlalchemy.ext.declarative import declarative_base 
import os 

sqldebug=True 

engine = create_engine('mysql://test:[email protected]/test1', 
      convert_unicode=True, 
      echo=sqldebug) 

#create_engine( 
#   'postgresql://user:[email protected]/clasificador', 
#   convert_unicode=True, 
#   echo=sqldebug) 

db_session = scoped_session(sessionmaker(autocommit=False, 
             autoflush=False, 
             bind=engine)) 
Base = declarative_base(bind=engine) 
Base.query = db_session.query_property() 

class Documento(Base): 
    '''Clase definiendo los documentos''' 
    __tablename__ = "documentos" 

    id = Column(Integer,primary_key=True) 
    nombre = Column(String(248)) 

    def __init__(self,nombre):   
     self.nombre = nombre 

    def __repr__(self): 
     return '<Documento %r>' % self.nombre 

Base.metadata.create_all(engine) 


from sqlalchemy.orm import sessionmaker 
#some other code 
Session = sessionmaker(bind=engine) 
session = Session() 
doc = Documento(os.path.basename('/tmp/test.py')) 
session.add(doc) #here fails 
session.commit() 

registro de salida

In [11]: ed /tmp/test.py 
Editing... done. Executing edited code... 
2011-11-18 08:48:41,254 INFO sqlalchemy.engine.base.Engine SELECT DATABASE() 
2011-11-18 08:48:41,254 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,259 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'character_set%%' 
2011-11-18 08:48:41,259 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,290 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names' 
2011-11-18 08:48:41,290 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,320 INFO sqlalchemy.engine.base.Engine SHOW COLLATION 
2011-11-18 08:48:41,320 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,339 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode' 
2011-11-18 08:48:41,339 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,343 INFO sqlalchemy.engine.base.Engine DESCRIBE `documentos` 
2011-11-18 08:48:41,343 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,389 INFO sqlalchemy.engine.base.Engine ROLLBACK 
2011-11-18 08:48:41,391 INFO sqlalchemy.engine.base.Engine 
CREATE TABLE documentos (
    id INTEGER NOT NULL AUTO_INCREMENT, 
    nombre VARCHAR(248), 
    PRIMARY KEY (id) 
) 


2011-11-18 08:48:41,391 INFO sqlalchemy.engine.base.Engine() 
2011-11-18 08:48:41,683 INFO sqlalchemy.engine.base.Engine COMMIT 
2011-11-18 08:48:41,698 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 
2011-11-18 08:48:41,700 INFO sqlalchemy.engine.base.Engine INSERT INTO documentos (nombre) VALUES (%s) 
2011-11-18 08:48:41,700 INFO sqlalchemy.engine.base.Engine ('test.py',) 
2011-11-18 08:48:41,701 INFO sqlalchemy.engine.base.Engine COMMIT 

Según registro, este código se agrega uno nuevo récord en dB. Si tiene cualquier otra consulta entonces su buena si te ayudo en eso :)

+0

Esto es raro, he ejecutado su código (cambiándolo a postgres) y funciona bien, lo he reorganizado a solo lo siguiente y todavía se ejecuta (con las importaciones a otro partes de mi código) Session = sessionmaker (bind = engine) session = Session() doc = Documento (os.path.basename ('/ tmp/test.py')) session.add (doc) # aquí falla session.commit() – Willyfrog

+0

He modificado la pregunta original para agregar el nuevo código, ya que no se puede ver correctamente aquí – Willyfrog

+2

Finalmente reescribí todo el código y funcionó, es casi lo mismo en diferentes archivos. Así que le doy la respuesta, ya que nunca habría tratado de escribirlo en otro archivo (y no debería ser una solución) – Willyfrog

0

No estoy tan familiarizado con sqlalchemy y su formato declarativo, pero una cosa que creo que no es correcta es que está sobrescribiendo el método init sin llamar al la clase de sus padres (aquí está Base).

Quite el init o llame al Base.init(self).

+0

Por esa parte, he seguido el tutorial de [frasco] (http://flask.pocoo.org/docs/patterns/sqlalchemy/) y funciona cuando uso frasco , sin quejas. Gracias de todos modos :) – Willyfrog

+0

Bien, pero recuerda que Flask podría estar agregando algo para que puedas definir ese método init. ¡En python + sqlalchemy puro eso puede no funcionar! – dario

+0

en cualquier otro caso, diría que es muy probable que sea correcto, pero incluso el tutorial sqlalchemy lo hace de esta manera, así que estaba seguro de que ese no era el problema. Gracias por señalarlo de todos modos :) – Willyfrog

28

he visto que el error antes de que se olvide de que si ForeignKey() toma el nombre de una tabla de tabla y campo, pero relationship() toma el nombre de una clase ORM en su lugar.Es decir, a veces escribo:

movie_id = Column(Integer, ForeignKey('movie.id')) 
movie = relationship('movie') # WRONG! 
# Exception: "SQLAlchemy expects to find an object…" 

Lo que debería ser en cambio la escritura, suponiendo que movie es el nombre de la tabla de base de datos (no es que SQL presta atención a nombre de la tabla de mayúsculas!) Y que Movie es el nombre de mi clase ORM Python, es:

movie_id = Column(Integer, ForeignKey('movie.id')) 
movie = relationship('Movie') # Works! 
+4

Guau, más de mil millones para esto. Hice eso exactamente. Esta incoherencia es algo terrible. – andronikus

+0

De hecho, ¡gracias! – AME

+2

Uno podría pensar que sqlalchemy podría emitir un mejor mensaje de error para ese tipo de error. De hecho, habiendo sido mordido por esto hoy, publicaré un informe de error. –

Cuestiones relacionadas