【发布时间】:2010-04-10 19:19:26
【问题描述】:
再次返回一些 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 时,它实际上是指使用唯一项目 ID 映射到字典的 Project 类(pid) 作为键。因此,当我通过每个学生的rank 和preferences 集合遍历每个学生时,它adds 不是项目ID,而是来自projects 字典中对项目ID 的引用。
students[sid].preferences[int(rank)].add(projects[int(pid)])
现在这对我来说非常有用,因为我可以找到所有我想要的关于学生首选项目的信息,而无需再次检查以获取有关项目 ID 的信息。您在错误中看到的表单将对象打印信息传递为:
return "%s %s (Supervisor id: %s)" %(self.proj_id, self.proj_name, self.proj_sup)
我的问题是:
我正在尝试将对象存储在数据库字段中,不是吗?
那么正确的方法是将项目信息(项目 ID、名称等)复制到其自己的表中,由唯一的项目 ID 引用吗?这样我就可以让其中一个学生表的项目 id 字段只是一个整数 id,当我需要更多信息时,只需
join表?其他表的等等?如果上面说得通,那么如何维护与一个表中作为另一表键索引的信息列的关系?
这是否归结为数据库设计问题?
还有其他优雅的方法可以实现这一点吗?
如果这是一个冗长的问题,我们深表歉意。解决这个问题对我来说非常重要,所以我试图尽可能多地解释,同时试图表明我正在尝试(可悲的是这里的关键词)来理解可能发生的事情错了。
【问题讨论】:
标签: python database-design sqlalchemy