SQLAlchemy - Mixin与MetaClass修改

时间:2011-07-14 22:31:18

标签: python sqlalchemy

所以说,例如,我有两个类:

Base = declarative_base()

class Vendor(Base):
  __tablename__ = "vendor"

  id          = Column(Integer, primary_key=True)
  name        = Column(String(45))

  def __init__(self, name):
    self.name = name

  def __repr__(self):
    return "<Vendor id=%d>" % self.id

class Site(Base):
  __tablename__ = "site"

  id          = Column(Integer, primary_key=True)
  vendor_id   = Column(Integer, ForeignKey('vendor.id'))

  vendor      = relation(Vendor)

  def __init__(self, name, code, location):
    self.name = name

  def __repr__(self):
    return "<Site id=%d>" % self.id

class SQLSchema:
  def __init__(self):
    self.engine       = create_engine('...', echo=False)
    self.metadata     = Base.metadata
    self.session = sessionmaker(bind=self.engine)()
    self.create()

  def create(self):
    self.metadata.create_all(self.engine)

我已经简化了类结构,现在,使用这些类,我可以使用:

sql = sqlschema.SQLSchema()

因此,有时,我希望轻松访问供应商,这意味着我可以使用:

v = sql.session.query(self).filter_by(name='test').one()

我更喜欢使用类似于(目前我的最大努力)来简化访问:

Vendor.get(sql.session, name='A-01')

让我感到震惊的是,get函数是非常通用的,我希望在从Base继承的所有类中使用它,并且我研究了这样做的最佳方法。我有两种方式可以想到:

  • 混合课程
  • 修改提供给declarative_base
  • 的元类

元类修改的示例

class MyDeclarativeMeta(DeclarativeMeta):
  def get(self, session, **filterargs):
    session.query(self).filter_by(**filterargs).one()

## ...
Base = declarative_base(metaclass=MyDeclarativeMeta)

我想尽可能少地创造一些东西。人们对我提出的选项有什么看法,是否有更好的方法?

1 个答案:

答案 0 :(得分:3)

对于简单的用例,Declarative不需要自定义元类,对于硬用例也几乎不需要自定义元类。 Mixins +定制基地应该能够完成所有的一切。

在基础上声明它:

class Base(object):
    def get(...):
        # ...

Base = declarative_base(cls=Base)

或使用mixin。