SQLAlchemy不支持类型错误 - 和表设计问题?

时间:2010-04-09 18:03:34

标签: python database-design 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类,唯一项目ID(pid)作为键。因此,当我通过他们的rankpreferences集迭代每个学生时,add不是项目ID,而是来自{{1}的项目ID的引用字典。

projects

现在这对我非常有用,因为我可以找到关于学生首选项目的所有内容,而无需再运行检查以获取有关项目ID的信息。您在错误中看到的表单将对象打印信息传递为:

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

我的问题是:

  1. 我正在尝试将对象存储在数据库字段中,不是吗?

  2. 那么,正确的方法是将项目信息(项目ID,名称等)复制到自己的表中,由唯一的项目ID引用吗?这样我可以让其中一个学生表的项目ID字段只是一个整数id,当我需要更多信息时,只需要表return "%s %s (Supervisor id: %s)" %(self.proj_id, self.proj_name, self.proj_sup) ?其他表格等等?

  3. 如果上述内容有意义,那么如何在一个表中维护与一列信息的关系,这是另一个表的关键索引?

  4. 这会归结为数据库设计问题吗?

  5. 还有其他优雅的方法来实现这个目标吗?

  6. 如果这是一个非常冗长的问题,请道歉。对我来说解决这个问题至关重要,所以我试图尽可能多地解释,同时试图表明我正在尝试(这里遗憾的关键词)来理解可能会发生什么错。

1 个答案:

答案 0 :(得分:4)

您是否期望SQLAlchemy将您的对象和对象集合神奇地转换为整数值?不可能。 SQLAlchemy可以将相关对象存储在单独的表中或序列化,但它没有心灵感应算法来阅读您的想法。所以你必须明确地描述你的选择。

您的问题的答案:

  1. 是的,添加到会话然后提交会将您的对象[s]存储到数据库。
  2. 是的,将相关对象存储在单独的表中是很常见的习惯用法。 SQLAlchemy处理得非常好,所以在大多数情况下你不需要明确指定连接。
  3. 关于此主题的SQLAlchemy教程中有good chapter
  4. 将相关对象存储在单独的表中不会导致数据库设计问题。在大多数情况下,这是习惯用法。
  5. 对于大多数情况,使用单独的表是最好的方法。但是还有一个PickleType列类型,它使用BLOB存储序列化对象。