SQLAlchemy не может установить ошибку атрибута при обновлении значения - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть таблица mailtable в серверной базе данных PostgreSQL, и я запрашиваю ее, используя SQLAlchemy ORM, используя заданную mailId.Для следующего кода amEngine уже настроен.Когда он достигает строки mailRow.usercomment = 'Hello World', он выдает:

AttributeError: невозможно установить атрибут

Base = declarative_base()
Base.metadata.reflect(amEngine)
metaAm = MetaData()
metaAm.reflect(bind=amEngine)
mt = metaAm.tables['mailtable']
Session = sessionmaker(bind=amEngine)
amSession = Session()
mailRow = amSession.query(
        mt
    ).filter(
        mt.c.id == mailId
    ).first()
mailAddress = mailRow.address
mailRow.usercomment = 'Hello World'
amSession.flush()
amSession.commit()

Мне нужно прочитать столбец address(успешно) и обновите столбец usercomment (выдает исключение).Тип PostgreSQL для обоих столбцов text.Как я могу это сделать?Я уверен, что это, должно быть, очень простая проблема, но для жизни я не вижу проблемы.

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Вы запрашиваете объект Table напрямую, а не через инструментальную модель:

mt = metaAm.tables['mailtable']
print(type(mt))
# <class 'sqlalchemy.sql.schema.Table'>

Когда вы запрашиваете таблицу, вам возвращается экземпляр <class 'sqlalchemy.util._collections.result'>, который является типом namedtuple.Кортежи являются неизменяемыми, поэтому вы не можете изменить значение их атрибутов.

0 голосов
/ 27 ноября 2018

Вызвав MetaData.reflect, вы попросили SQLAlchemy автоматически определить объекты Table, описывающие вашу базу данных.Вы можете использовать эти объекты для создания SQL-запросов, не зависящих от языка, таких как

engine.execute(update(mt).where(mt.c.id==1).values(usercomment='Hello World'))

Однако вы пока не можете использовать объекты Table для правильного ORM.Когда вы запрашиваете объект Table (через session.query(mt)), вы получаете результаты, возвращаемые вам как namedtuple -подобные объекты, доступные только для чтения.Установка их атрибутов не имеет смысла, поэтому вы наблюдаете исключение.

Чтобы использовать реальный ORM, вам нужно создать соответствующие классы ORM и сопоставить их с Table объектами.

КонечноВы можете попросить SQLAlchemy автоматически отразить для вас классы ORM вместе с таблицами, используя automap .Вот код, который вы, вероятно, хотели написать:

from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import sessionmaker

# Ask SQLAlchemy to reflect the tables and 
# create the corresponding ORM classes:
Base = automap_base()
Base.prepare(amEngine, reflect=True)

# This is the ORM class we are interested in:
MailTable = Base.classes.mailtable

# Create the session, query, update and commit:
Session = sessionmaker(bind=amEngine)
session = Session()
mailRow = session.query(MailTable).get(mailId)
mailAddress = mailRow.address
mailRow.usercomment = 'Hello World'
session.commit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...