Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy expects an object, but finds a Table

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

like image 479
Willyfrog Avatar asked Nov 17 '11 16:11

Willyfrog


1 Answers

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!
like image 150
Brandon Rhodes Avatar answered Oct 10 '22 13:10

Brandon Rhodes