SQLAlchemy - модификация Mixin против MetaClass - PullRequest
2 голосов
/ 15 июля 2011

Так, например, у меня есть два класса:

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 Ответ

3 голосов
/ 15 июля 2011

Пользовательские метаклассы не нужны с декларативным для простых случаев использования, и в значительной степени совсем не для сложных случаев использования. Mixins + пользовательские базы должны уметь делать практически все.

Объявите это на основании:

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

Base = declarative_base(cls=Base)

или используйте миксин.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...