SQLAlchemy ожидает объект, но находит таблицу - PullRequest
12 голосов
/ 17 ноября 2011

Я сейчас начинаю с sqlalchemy. В моем текущем проекте мне нужно сделать какую-то часть с Flask, а другую часть из командной строки. Часть о фляге работает нормально, взаимодействует с sqlalchemy и всем, но часть командной строки - нет.

Я получаю ошибку

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

Я попытал счастья с Google и читал декларативную sqlalchemy, но не могу найти, в чем может быть проблема. Код в модуле:

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 - это модуль, в котором у меня есть общий код для sqlalchemy. большинство из них происходит из документации по фляге, а db_session используется только для фляги, я сделал другой сеанс для другого модуля.

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

Наконец, здесь находится модуль «documentmento», хотя я сомневаюсь, что проблема здесь. из sqlalchemy import Column, Integer, String из базы данных импорта базы данных

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

Некоторые комментарии / имена написаны на испанском языке, но я думаю, что вы можете спокойно их игнорировать, если потребуется, я сделаю перевод

Следуя коду Lafada, я создал еще один файл с:

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

и все работает отлично. Единственное отличие, которое я могу заметить, это то, как создается сессия, я также изменил это в своем исходном коде, но он продолжает получать ту же ошибку.

Я нашел виновника, он был не в коде, который я показываю, а в другом классе, который пытался создать с ним связь, но связывал его с таблицей, а не с объектом. Пока я не попробовал несколько других вещей, я не мог отследить это до настоящей проблемы

Ответы [ 3 ]

28 голосов
/ 05 марта 2012

Я уже видел эту ошибку раньше, если забыл, что ForeignKey() принимает имя таблицы и поля базы данных, а relationship() принимает имя класса ORM. То есть я иногда пишу:

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

То, что я должен вместо этого написать, предполагая, что movie - это имя таблицы базы данных (не то, что SQL обращает внимание на использование заглавных букв в именах таблиц!) И что Movie - это имя моего Python ORM-класса:

movie_id = Column(Integer, ForeignKey('movie.id'))
movie = relationship('Movie')  # Works!
6 голосов
/ 18 ноября 2011

Я попробовал ваш код на mysql (у меня на компьютере нет postgress :(). Я помещаю этот код сюда, пожалуйста, проверьте это, потому что он работает нормально для меня.

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

Выходной журнал

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

Согласно журналу, этот код добавит одну новую запись в дБ. Если у вас есть какой-либо другой запрос, то хорошо, если я вам в этом помогу:)

0 голосов
/ 17 ноября 2011

Я не очень знаком с sqlalchemy и его декларативным форматом, но одна вещь, которую я считаю неправильной, это то, что вы перезаписываете метод init без вызова класса его родителя (здесь это Base).

Удалите init или позвоните Base.init(self).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...