У меня есть следующая проблема:
У меня есть класс:
class Word(object):
def __init__(self):
self.id = None
self.columns = {}
def __str__(self):
return "(%s, %s)" % (str(self.id), str(self.columns))
self.columns является dict, который будет содержать (columnName:columnValue) значения. Название столбцов известно во времени выполнения, и они загружаются в списке wordColumns, например
wordColumns = ['english', 'korean', 'romanian']
wordTable = Table('word', metadata,
Column('id', Integer, primary_key = True)
)
for columnName in wordColumns:
wordTable.append_column(Column(columnName, String(255), nullable = False))
Я даже создал явный картопостроитель свойства, чтобы "вынудить" столбцы таблицы быть отображенными на word.columns[columnName] вместо word.columnName, я не получаю ошибки на отображении, но кажется, что это не работает.
mapperProperties = {}
for column in wordColumns:
mapperProperties['columns[\'%']' % column] = wordTable.columns[column]
mapper(Word, wordTable, mapperProperties)
Когда я загружаю объект слова, SQLAlchemy создает объект, который имеет word.columns ['английский язык'], word.columns ['корейский язык'] и т.д. свойства вместо того, чтобы загрузить их в word.columns dict. Таким образом для каждого столбца, это создает новое свойство. Кроме того, словарь word.columns не делает даже существует.
Тот же путь, когда я пытаюсь сохранить слово, SQLAlchemy, ожидает находить значения столбцов в свойствах названными как word.columns ['английский язык'] (строковый тип) вместо словаря word.columns.
Я должен сказать, что мой опыт с Python и SQLAlchemy вполне ограничен, возможно, не возможно сделать то, что я пытаюсь сделать.
Любая ценившая справка,
Заранее спасибо.
Похоже, вы можете просто использовать атрибуты напрямую вместо использования столбцов
dict
.
Рассмотрим следующую настройку:
from sqlalchemy import Table, Column, Integer, Unicode, MetaData, create_engine
from sqlalchemy.orm import mapper, create_session
class Word(object):
pass
wordColumns = ['english', 'korean', 'romanian']
e = create_engine('sqlite://')
metadata = MetaData(bind=e)
t = Table('words', metadata, Column('id', Integer, primary_key=True),
*(Column(wordCol, Unicode(255)) for wordCol in wordColumns))
metadata.create_all()
mapper(Word, t)
session = create_session(bind=e, autocommit=False, autoflush=True)
С этим пустым классом вы можете сделать:
w = Word()
w.english = u'name'
w.korean = u'이름'
w.romanian = u'nume'
session.add(w)
session.commit()
И когда вы хотите получить доступ к данным:
w = session.query(Word).filter_by(english=u'name').one()
print w.romanian
Это весь sqlalchemy
ORM point , вместо использования кортежа
или dict
для доступа к данным вы используете доступ , подобный атрибуту , к своему собственному классу.
Мне было интересно, почему вы хотели бы использовать дикт
. Возможно, это потому, что у вас есть строки с названиями языков. Что ж, для этого вы можете использовать python getattr
и setattr
вместо этого, как и для любого объекта python:
language = 'korean'
print getattr(w, language)
Это должно решить все ваши проблемы.
Тем не менее, если вы все еще хотите использовать dict
-подобный доступ к столбцам, это также возможно. Вам просто нужно реализовать объект, подобный dict
. Теперь я предоставлю код для этого, хотя я считаю, что это совершенно ненужный беспорядок, поскольку доступ к атрибутам настолько чистый. Если ваша проблема уже решена с помощью описанного выше метода, не используйте приведенный ниже код.
Вы можете сделать это в классе Word
:
class Word(object):
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
Остальная часть настройки работает, как указано выше. Затем вы можете использовать его так:
w = Word()
w['english'] = u'name'
Если вам нужен атрибут columns
, тогда вам понадобится dict
-подобный
class AttributeDict(DictMixin):
def __init__(self, obj):
self._obj = obj
def __getitem__(self, item):
return getattr(self._obj, item)
def __setitem__(self, item, value):
return setattr(self._obj, item, value)
class Word(object):
def __init__(self):
self.columns = AttributeDict(self)
Затем вы можете использовать по своему усмотрению:
w = Word()
w.columns['english'] = u'name'
Думаю, вы согласитесь, что все это излишне сложно и без дополнительных преимуществ.