sqlalchemy 查找表
你好,我有一个符合第三范式的表格
ftype_table = Table(
'FTYPE',
Column('ftypeid', Integer, primary_key=True),
Column('typename', String(50)),
base.metadata,
schema='TEMP')
file_table = Table(
'FILE',
base.metadata,
Column('fileid', Integer, primary_key=True),
Column('datatypeid', Integer, ForeignKey(ftype_table.c.datatypeid)),
Column('size', Integer),
schema='TEMP')
还有一些映射器
class File(object): pass
class FileType(object): pass
mapper(File, file_table, properties={'filetype': relation(FileType)})
mapper(FileType, file_table)
假设Ftype表里有1:TXT、2:AVI、3:PPT这些类型
我想做的是,如果我这样创建一个文件对象:
file=File()
file.size=10
file.filetype= FileType('PPT')
Session.save(file)
Session.flush()
那么File表里会包含fileid:xxx,size:10,datatypeid:3
不幸的是,这样会在FileType表里添加一条记录,而这个ID也会传到File表里。
有没有什么聪明的方法可以用sqlalchemy来实现这个,而不需要去查询FileType表来检查这个条目是否存在呢?
谢谢
3 个回答
0
只需要创建一个文件类型对象的缓存,这样在你第一次使用某种文件类型时,数据库查询只会发生一次:
class FileTypeCache(dict): def __missing__(self, key): obj = self[key] = Session.query(FileType).filter_by(typename=key).one() return obj filetype_cache = FileTypeCache() file=File() file.size=10 file.filetype= filetype_cache['PPT']
这样应该可以正常工作,前提是没有拼写错误。
2
这里提到的UniqueObject方法是一个标准的解决方案,具体可以查看这个链接:http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject。这个方法的核心思想是重写File
的创建过程,使用__metaclass__.call()
或者File.__new__()
,这样可以返回已经存在的对象,这个对象可能来自数据库或者缓存(如果对象在数据库中不存在,第一次查找是不可避免的,除非使用了围绕MySQL的REPLACE构建的某种方法)。
补充一下:因为我一直在研究使用方法,所以我对这个唯一对象的方法进行了重写,使其更易于移植,并且更新到了0.5/0.6版本。
0
因为 declarative_base 和 zzzeek 的代码在 sqlalchemy 0.4 版本中无法使用,所以我用了下面的缓存,这样即使新对象不在数据库中,它们也能保持唯一性。
class FileTypeCache(dict):
def __missing__(self, key):
try:
obj = self[key] = Session.query(FileType).filter_by(typename=key).one()
return obj
except InvalidRequestError:
return obj=self[key]= FileType(key)
return obj
重写 eq 方法来处理 FileType。
class FileType(object):
def __init__(self, typename)
self.typename=typename
def __eq__(self):
if isinstance(other, FileType):
return self.typename == other.typename
else:
return False