嗨我有一张3NF格式的表格
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')
和mappers
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()
file.size=10
file.filetype= FileType('PPT')
Session.save(file)
Session.flush()
是File表包含fileid:xxx,size:10, datatypeid:3
不幸的是,一个条目被添加到FileType表中,并且该id被传播到File表。
是否有一种聪明的方法可以使用sqlalchemy实现上述功能,而无需在FileType表上进行查询以查看条目是否存在
由于
答案 0 :(得分:2)
UniqueObject配方是这里的标准答案:http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject。我们的想法是使用File
或__metaclass__.call()
覆盖File.__new__()
的创建,以从DB或缓存中返回已存在的对象(如果对象不是,则返回初始数据库查找)已经存在,显然是不可避免的,除非使用围绕MySQL的REPLACE构建的东西。)
编辑:因为我一直在研究使用方法,所以我重写了独特的对象配方,使其更加便携,并且更新为0.5 / 0.6。
答案 1 :(得分:0)
只需创建FileType对象的缓存,以便仅在第一次使用给定文件类型时才进行数据库查找:
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 :(得分:0)
由于declarative_base和zzzeek代码不适用于sqlalchemy 0.4,我 使用以下缓存,以便新对象在db
中不存在时也保持唯一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
覆盖FileType
的 eqclass FileType(object):
def __init__(self, typename)
self.typename=typename
def __eq__(self):
if isinstance(other, FileType):
return self.typename == other.typename
else:
return False