2011-11-17 4 views
12

Attualmente sto iniziando con SQLAlchemy. Nel mio progetto attuale devo fare una parte con Flask e qualche altra parte dalla riga di comando. La parte relativa al pallone funziona bene, si interfaccia con sqlalchemy e tutto, ma la parte commandline non lo è.SQLAlchemy si aspetta un oggetto, ma trova una tabella

L'errore che sto ottenendo è

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)'.",) 

ho provato la mia fortuna con Google e la lettura SQLAlchemy dichiarativa, ma non riesco a trovare quello che potrebbe essere il problema. Il codice nel modulo è:

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 è il modulo in cui ho il codice comune per SQLAlchemy. la maggior parte proviene dalla documentazione del pallone e db_session è usato solo per il pallone, ho fatto una sessione diversa per l'altro modulo.

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

Infine, ecco il modulo "documento", anche se dubito che il problema sia qui. da Colonna SQLAlchemy importazione, Integer, String da db Base importazione

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 

Alcuni dei commenti/nomi sono in spagnolo, ma penso che si possono tranquillamente ignorare, se è necessario, farò le traduzioni

seguito il codice di Lafada ho creato un altro file con un semplice:

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

e funziona bene. L'unica differenza che posso individuare è come viene creata la sessione, l'ho modificata anche nel mio codice originale, ma continua a generare lo stesso errore.

Ho trovato il colpevole, non era sul codice che sto mostrando, ma in una classe diversa che stava cercando di creare una relazione con esso, ma il collegamento al tavolo invece dell'oggetto. Fino a quando ho provato diverse altre cose, non riuscivo a rintracciarlo al vero problema

risposta

6

ho provato il codice su mysql (Non ho Postgress nel mio pc :(). Sto mettendo il codice qui si prega di verificare che perché questo sta lavorando bene per me.

#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 di uscita

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 

Come per registro, questo codice si aggiungerà un nuovo record nel db. Se avete qualche altra domanda quindi la sua buona se vi aiuto in quel :)

+0

Questo è strano, ho eseguito il tuo codice (cambiandolo in postgres) e funziona bene, l'ho riorganizzato al seguente e continua a funzionare (con le importazioni in altri parti del mio codice) Session = sessionmaker (bind = motore) session = Session() doc = documento (os.path.basename ('/ tmp/test.py')) session.add (doc) # qui fallisce session.commit() – Willyfrog

+0

Ho modificato la domanda originale per aggiungere il nuovo codice, in quanto non può essere visto correttamente qui – Willyfrog

+2

Ho finalmente riscritto tutto il codice e ha funzionato, è quasi la stessa in diversi file. Quindi ti premo la risposta come non avrei mai provato a scriverlo in un altro file (e non dovrebbe essere una soluzione) – Willyfrog

0

Non ho molta familiarità con sqlalchemy e il suo formato dichiarativo, ma una cosa che penso non sia corretta è la sovrascrittura del metodo init senza chiamare il la classe del genitore (qui è Base).

Rimuovere il init o chiamare Base.init(self).

+0

Per la parte, ho seguito il tutorial da [boccetta] (http://flask.pocoo.org/docs/patterns/sqlalchemy/) e funziona quando uso pallone , senza lamentarsi. Grazie comunque :) – Willyfrog

+0

Ok, ma ricorda che Flask potrebbe aggiungere qualcosa per poter definire il metodo init. In puro pitone + sqlalchemy che potrebbe non funzionare! – dario

+0

in ogni altro caso, direi che è più probabile che sia corretto, ma anche il tutorial di sqlalchemy fa così, quindi ero certo che non fosse questo il problema. Grazie per averlo indicato comunque :) – Willyfrog

28

ho visto che errore prima se io dimenticare che ForeignKey() prende il nome di un database tavolo-e-campo, ma che relationship() prende il nome di una classe ORM, invece.Cioè, a volte scrivo:

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

cosa dovrei invece la scrittura, partendo dal presupposto che movie è il nome della tabella di database (non che SQL presta attenzione al nome della tabella capitalizzazione!) E che Movie è il nome del il mio Python classe ORM, è:

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

Wow, + un miliardo per questo. Ho fatto quella cosa esatta. Questa incoerenza è terribile. – andronikus

+0

Infatti, grazie! – AME

+2

Si potrebbe pensare che sqlalchemy possa emettere un messaggio di errore migliore per questo tipo di errore. Infatti, essendo stato morso da questo oggi, posterò un bug report. –