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 个回答
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)
看起来一切都正常。
2
你也可以使用列的复制方法吗?这样的话,字段就可以独立于表格来定义,而那些被重复使用的字段只需要用field.copy()来复制就可以了。
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()
#...
14
你可以把一些共同的属性提取到一个叫做混合类(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']
编辑: 你可能会想,这样做会让C1
和C2
共享同一个Column
对象,但正如SQLAlchemy的文档所提到的,来自混合类的Column对象是会被复制的。我已经更新了代码示例来展示这个行为。