SQLAlchemy:避免在声明式样式类定义中重复

时间:2010-09-02 11:49:35

标签: python sqlalchemy

我正在使用SQLAlchemy,我的对象模型中的许多类具有相同的两个属性:id和(整数&主键)和name(字符串)。我试图避免在每个类中声明它们如此:

class C1(declarative_base()):
    id = Column(Integer, primary_key = True)
    name = Column(String)
    #...

class C2(declarative_base()):
    id = Column(Integer, primary_key = True)
    name = Column(String)
    #...

这样做的好方法是什么?我尝试过使用元类,但它还没有用。

3 个答案:

答案 0 :(得分:10)

您可以将常用属性分解为mixin class,然后将其与declarative_base()一起多次继承:

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

class IdNameMixin(object):
    id = Column(Integer, primary_key=True)
    name = Column(String)

class C1(declarative_base(), IdNameMixin):
    __tablename__ = 'C1'

class C2(declarative_base(), IdNameMixin):
    __tablename__ = 'C2'

print C1.__dict__['id'] is C2.__dict__['id']
print C1.__dict__['name'] is C2.__dict__['name']

编辑:您可能认为这会导致C1C2共享相同的Column个对象,但正如SQLAlchemy docs中所述,当源自mixin类时,列对象被复制。我已更新代码示例以演示此行为。

答案 1 :(得分:2)

你还可以使用Column的复制方法吗?这样,可以独立于表定义字段,而那些重用的字段只是field.copy() - ed。

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

class C1(declarative_base()):
    id = id.copy()
    name = name.copy()
    #...

class C2(declarative_base()):
    id = id.copy()
    name = name.copy()
    #...

答案 2 :(得分:1)

我想我已经开始工作了。

我创建了一个派生自DeclarativeMeta的元类,并使其成为C1和C2的元类。在那个新的元类中,我只是说

def __new__(mcs, name, base, attr):
  attr['__tablename__'] = name.lower()
  attr['id'] = Column(Integer, primary_key = True)
  attr['name'] = Column(String)
  return super().__new__(mcs, name, base, attr)

似乎工作正常。