Reputation: 485
I'm currently starting with sqlalchemy. In my current project I have to do some part with Flask and some other part from the command line. The part about flask is running fine, interfacing with sqlalchemy and all, but the commandline part is not.
The error I'm getting is
ArgumentError("Class object expected, got 'Table('documentos',
MetaData(bind=Engine(postgresql://user:password@localhost/clasificador)),
Column('id', Integer(), table=<documentos>, primary_key=True, nullable=False),
Column('nombre', String(length=248), table=<documentos>), schema=None)'.",)
I've tried my luck with google and reading declarative sqlalchemy, but I can't find what could be the problem. The code in the module is:
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 is the module where I have the common code for sqlalchemy. most of it comes from flask documentation, and db_session is used only for flask, I made a different session for the other module.
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:passwd@localhost/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()
Finally, here is the "documento" module, although I doubt the problem is here. from sqlalchemy import Column, Integer, String from db import Base
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
Some of the comments/names are in spanish, but I think you can safely ignore them, if it's necessary I'll do the translations
Following Lafada's code I've created another file with just:
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()
and it runs just fine. The only difference I can spot is how the session is created, I've modified that as well in my original code, but it keeps getting the same error.
I found the culprit, it wasn't on the code I'm showing, but in a different class which was trying to create a relationship with it but linking to the table instead of the object. Until i tried several other things I couldn't trace it to the real problem
Upvotes: 13
Views: 11833
Reputation: 89425
I have seen that error before if I forget that ForeignKey()
takes the name of a database table-and-field but that relationship()
takes the name of an ORM class instead. That is, I sometimes write:
movie_id = Column(Integer, ForeignKey('movie.id'))
movie = relationship('movie') # WRONG!
# Exception: "SQLAlchemy expects to find an object…"
What I should instead be writing, assuming that movie
is the name of the database table (not that SQL pays attention to table name capitalization!) and that Movie
is the name of my Python ORM class, is:
movie_id = Column(Integer, ForeignKey('movie.id'))
movie = relationship('Movie') # Works!
Upvotes: 29
Reputation: 21243
I tried your code on mysql (I Dont have postgress in my pc :(). I am putting that code here please check that because that is working fine for 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:test@localhost/test1',
convert_unicode=True,
echo=sqldebug)
#create_engine(
# 'postgresql://user:passwd@localhost/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()
Output log
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
As per log, this code will add one new record in db. If you have any other query then its good if I help you in that :)
Upvotes: 6
Reputation: 300
I am not so familiar with sqlalchemy and its declarative format but one thing that I think is not correct is you are overwriting the init
method without calling the its parent's class (here it is Base
).
Remove the init
or call Base.init(self)
.
Upvotes: 0