添加到sqlalchemy映射类非db属性

时间:2017-05-30 19:23:52

标签: python sqlalchemy

应用程序具有这样的逻辑:存储在数据库中的人员列表,每个人都有实时计算的评级,并且该值永远不会存储在数据库中。我想使用一个类来处理dababase字段:名称,年龄等和非数据库字段:rating。

sqlalchemy有可能吗?现在我正在使用继承Man - > ManMapping:

class Man:
  rating = None

  def get_rating(self):
    return self.rating

  ...

class ManMapping(Base, Man):
  __tablename__ = 'man'
  id = Column('man_id', Integer, primary_key=True)
  name = Column(Unicode)

  ...

它有效,但对我来说看起来很糟糕。这是正确的方法还是我必须做别的事情?

3 个答案:

答案 0 :(得分:1)

如果您使用数据库中的任何数据来计算评分,我建议您查看hybrid property。否则,我会将self.rating添加到 init ,并将您的函数放在ManMapping类中。类似的东西:

class ManMapping(Base):   
    __tablename__ = 'man'   
    id = Column('man_id', Integer, primary_key=True)   
    name = Column(Unicode)

   def __init__(self)
       self.rating = None

   def get_rating(self):
       return self.rating

答案 1 :(得分:1)

在我看来,你应该有两个不同的类。 一个用于代码中的逻辑,另一个用于与数据库通信。

gk

您应该有一个提供程序,使用 ManModel 对象对DB进行查询,然后将结果映射到 Man 对象,并将映射数据返回给调用者。 您的应用程序将仅使用 Man 对象,您的提供程序将执行映射。 如下所示:

// f helper
let fk = (n, k) => {
  if (n < 10)
    return gk(n + 1, g => k("f" + g))
  else
    return k("f")
}
    
// g helper
let gk = (n, k) => {
  if (n < 10)
    return fk(n + 1, f => k("g" + f))
  else
    return k("g")
}
    
let f = n =>
  fk(n, x => x)

let g = n =>
  gk(n, x => x)
  
console.log(f(0))  // fgfgfgfgfgf
console.log(g(0))  // gfgfgfgfgfg
console.log(f(5))  // fgfgfg
console.log(g(5))  // gfgfgf
console.log(f(11)) // f
console.log(g(11)) // g

答案 2 :(得分:0)

这是正确的解决方案:https://docs.sqlalchemy.org/en/13/orm/constructors.html 混合属性的灵活性稍差一些。接受的答案不是问题的实际答案。

从数据库行重新创建对象时,SQLAlchemy ORM不调用 init 。 ORM的过程有点类似于Python标准库的pickle模块,它调用了底层的 new 方法,然后直接在实例上静默还原属性,而不是调用 init

如果在准备使用数据库加载的实例之前需要对其进行一些设置,则可以使用一个名为InstanceEvents.load()的事件挂钩来实现此目的;也可以通过称为reconstructor()的特定于类的装饰器来使用它。当使用constructor()时,映射器每次加载或重建该类的实例时都将不带任何参数地调用修饰的方法。这对于重新创建通常在 init 中分配的瞬态属性很有用:

from sqlalchemy import orm

class MyMappedClass(object):
    def __init__(self, data):
        self.data = data
        # we need stuff on all instances, but not in the database.
        self.stuff = []

    @orm.reconstructor
    def init_on_load(self):
        self.stuff = []