Еще раз с некоторыми синтаксисами SQLAlchemy.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
, он не является идентификатором проекта, а ссылкой на идентификатор проекта из 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)
Мои вопросы:
Я пытаюсь сохранить объект в поле базы данных, не так ли?
Правильно ли будет копирование информации о проекте (идентификатор проекта, имя и т. Д.) В его собственную таблицу, на которую ссылается уникальный идентификатор проекта? Таким образом, я могу просто иметь поле id проекта для одной из таблиц учеников, просто быть целым id, и когда мне нужна дополнительная информация, просто
join
таблицы? Так и так далее для других столов?Если это имеет смысл, то как поддерживать связь с столбцом информации в одной таблице, которая является ключевым индексом в другой таблице?
Означает ли это, что проблема с базой данных?
Есть ли другие элегантные способы решения этой задачи?
Извините, если это очень длинный вопрос. Для меня очень важно решить эту проблему, поэтому я попытался объяснить как можно больше, пытаясь показать, что я пытается найти (ключевое слово здесь печально), чтобы понять, что может быть неправильным.
Я понял, что даже если в моей таблице указаны только два столбца: 'sid' и' name', я могу получить другую информацию, такую как alloc_project, используя (например) 'student.allocated_project' , Просто добавление его в столбе стола приводит к хаосу. Я попытался использовать 'PickleType', но получаю сообщение об ошибке в строках' Объекты, хранящиеся в PickleType, когда mutable = True должен реализовать __eq __() для надежного сравнения. ' – PizzAzzra
В некотором смысле предыдущий код фактически связывал Student и Классы проектов с использованием словаря 'projects'. Тем не менее, просто для того, чтобы держать вещи дискретными, я только что добавил в класс Student 'alloc_proj_ref', который становится внешним ключом в' projects_table' и как таковой, я могу обойтись без 'alloc_project'. Однако мне все же нужно использовать его для моего алгоритма распределения. – PizzAzzra
Сообщение об ошибке для 'PickleType' верное: SQLAlchemy должно знать, изменяется ли объект и должен быть обновлен в базе данных. Поэтому вы должны предоставить метод '__eq__' - способ получить эту информацию. –