开发者

SQLAlchemy - Mixin vs MetaClass modification

开发者 https://www.devze.com 2023-03-20 05:36 出处:网络
So say, for example I have two classes: Base = declarative_base() class Vendor(Base): __tablename__ = \"vendor\"

So say, for example I have two classes:

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):
    sel开发者_开发问答f.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)

I've simplified the class structure, now, using these classes, I can use:

sql = sqlschema.SQLSchema()

So, at times, I want easy access to a Vendor, which means I can use:

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

I'd prefer to simplify the access by using akin to (currently my best effort):

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

It struck me, that the get function is pretty generic that I'd want across all my classes that inherit from Base and I looked into the best way of doing this. There are two ways I can think of:

  • a Mix-in class
  • Modifying the metaclass supplied to declarative_base

Example of the metaclass modification

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

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

I'd like to create something with the least surprise possible. What are people's opinions on the options I've presented and is there a better way altogether?


Custom metaclasses aren't needed with Declarative for simple use cases, and pretty much not at all for hard use cases either. Mixins + custom bases should be able to do pretty much everything.

Declare it on the base:

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

Base = declarative_base(cls=Base)

or use a mixin.

0

精彩评论

暂无评论...
验证码 换一张
取 消