Ошибка неподдерживаемого типа в SQLAlchemy - и проблемы с дизайном таблицы? - PullRequest
1 голос
/ 09 апреля 2010

вернемся снова с еще несколькими махинациями SQLAlchemy.

Позвольте мне пройти через это.

Моя таблица теперь настроена так:

engine = create_engine('sqlite:///:memory:', echo=False)
metadata = MetaData()
students_table = Table('studs', metadata,
    Column('sid', Integer, primary_key=True),
    Column('name', String),
    Column('preferences', Integer),
    Column('allocated_rank', Integer),
    Column('allocated_project', Integer)
)
metadata.create_all(engine)
mapper(Student, students_table)  

Довольно просто, и по большей части я наслаждался возможностью запрашивать практически любую информацию, которую хочу, при условии, что я избегаю описанных ниже ошибок.

Класс, из которого он сопоставлен:

class Student(object):
    def __init__(self, sid, name):
        self.sid = sid
        self.name = name
        self.preferences = collections.defaultdict(set)
        self.allocated_project = None
        self.allocated_rank = 0

def __repr__(self):
    return str(self)

def __str__(self):
    return "%s %s" %(self.sid, self.name)  

Объяснение: preferences - это в основном набор всех проектов, которые студент предпочел бы назначить. Когда включается алгоритм распределения, ученик allocated_project выходит из этого набора предпочтений.

Теперь, если я попытаюсь сделать это:

for student in students.itervalues():
    session.add(student)

session.commit()

Выдает две ошибки: одну для столбца allocated_project (см. Ниже) и аналогичную ошибку для столбца preferences:

sqlalchemy.exc.InterfaceError: (InterfaceError) Error binding parameter 4 
- probably unsupported type. u'INSERT INTO studs (sid, name, allocated_rank, 
allocated_project) VALUES (?, ?, ?, ?, ?, ?, ?)' 
[1101, 'Muffett,M.', 1, 888 Human-spider relationships (Supervisor id: 123)]  

Если я вернусь к своему коду, то обнаружу, что когда я копирую preferences из заданных текстовых файлов, он фактически ссылается на класс Project, который отображается в словарь с использованием уникального идентификатора проекта. (pid) в качестве ключей. Таким образом, когда я перебираю каждого учащегося через rank и набор preferences, он add не является идентификатором проекта, а ссылкой на идентификатор проекта из словаря projects.

students[sid].preferences[int(rank)].add(projects[int(pid)])

Теперь это очень полезно для меня, так как я могу узнать все, что хочу, о предпочитаемых студентом проектах, не выполняя еще одну проверку для получения информации об идентификаторе проекта. Форма, которую вы видите в ошибке, содержит информацию о печати объекта:

return "%s %s (Supervisor id: %s)" %(self.proj_id, self.proj_name, self.proj_sup)

Мои вопросы:

  1. Я пытаюсь сохранить объект в поле базы данных, не так ли?

  2. Правильно ли будет тогда копировать информацию о проекте (идентификатор проекта, имя и т. Д.) В свою собственную таблицу, на которую ссылается уникальный идентификатор проекта? Таким образом, у меня может быть просто поле идентификатора проекта для одной из таблиц ученика, просто целочисленный идентификатор, а когда мне нужно больше информации, просто join таблицы? И так далее для других таблиц?

  3. Если вышеизложенное имеет смысл, то как сохранить связь со столбцом информации в одной таблице, который является ключевым индексом для другой таблицы?

  4. Это сводится к проблеме проектирования базы данных?

  5. Существуют ли другие элегантные способы сделать это?

Извините, если это очень затянувшийся вопрос. Для меня очень важно решить эту проблему, поэтому я постарался объяснить как можно больше, пытаясь показать, что я пытаюсь (ключевое слово здесь, к сожалению) понять, что может быть не так .

1 Ответ

4 голосов
/ 10 апреля 2010

Ожидаете ли вы, что SQLAlchemy волшебным образом преобразует ваш объект и коллекцию объектов в целочисленные значения? Это невозможно. SQLAlchemy может хранить связанные объекты в отдельных таблицах или сериализованных, но у него нет телепатических алгоритмов, чтобы читать ваши мысли. Таким образом, вы должны описать свой выбор явно.

Ответы на ваши вопросы:

  1. Да, добавление в сеанс и последующая фиксация сохранят ваш объект [ы] в базе данных.
  2. Да, хранение связанных объектов в отдельной таблице - довольно распространенная идиома. SQLAlchemy обрабатывает довольно хорошо, поэтому вам не нужно явно указывать объединения в большинстве случаев.
  3. В руководстве по SQLAlchemy есть хорошая глава .
  4. Хранение связанных объектов в отдельной таблице не вызывает проблем проектирования базы данных. Это идиома используется в большинстве случаев.
  5. Использование отдельной таблицы - лучший способ для большинства случаев. Но есть также тип столбца PickleType, который использует BLOB для хранения сериализованного объекта.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...