【问题标题】:sqlalchemy lookup tablessqlalchemy 查找表
【发布时间】:2019-01-09 23:10:50
【问题描述】:

您好,我有一张 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')                                                                

和映射器

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()

是文件表包含fileid:xxx,size:10,datatypeid:3

不幸的是,一个条目被添加到 FileType 表中,并且这个 id 被传播到 File 表中。

是否有一种聪明的方法可以使用 sqlalchemy 实现上述目标,而无需对 FileType 表进行查询以查看条目是否存在

谢谢

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    只需创建一个 FileType 对象的缓存,以便数据库查找仅在您第一次使用给定文件类型时发生:

    类文件类型缓存(字典): def __missing__(self, key): obj = self[key] = Session.query(FileType).filter_by(typename=key).one() 返回对象 文件类型缓存 = 文件类型缓存() 文件=文件() 文件大小=10 file.filetype=filetype_cache['PPT']

    应该可以,模数错别字。

    【讨论】:

    • 这是正确的方向,但是 1) __missing__ 不会用新值更新缓存,2) 手动缓存的对象在从会话中删除时应该小心处理。
    • 糟糕,已修复缓存逻辑。感谢您的关注。
    【解决方案2】:

    UniqueObject 配方是这里的标准答案:http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject。这个想法是使用__metaclass__.call()File.__new__() 来覆盖File 的创建,以从数据库或缓存中返回已经存在的对象(如果对象不存在,则初始数据库查找是除非使用围绕 MySQL 的 REPLACE 构建的东西,否则显然是不可避免的)。

    编辑:由于我一直在研究使用配方,我重写了独特的对象配方,使其更便携,并针对 0.5/0.6 进行了更新。

    【讨论】:

    • 看起来不错。不幸的是,我正在使用 db2 并坚持使用 sqlalchemy 0.4.0 是否有 0.4.0 版本
    【解决方案3】:

    由于 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

    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
    

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 2011-11-25
      • 2019-11-05
      • 2015-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多