sqlalchemy查找表

时间:2009-12-27 00:37:15

标签: sqlalchemy

嗨我有一张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表上进行查询以查看条目是否存在

由于

3 个答案:

答案 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

eq
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