Java においては、エンティティクラスで共通の列(カラム)は、基底クラスで定義して
継承クラスで解決していた。
同じ感覚で、Python SQLAlchemy で構成しようとしても、
Java と同様の単一継承の方法ではできない。
Python クラスの多重継承の方法で共通カラムの定義を行う。
【サンプル】
前提として、エンティティクラスは、dict 辞書型を返すメソッドと
JSON を返すメソッドを保有しているものとする。
最初の前提の為の基底クラス
entitybase.py
from datetime import date, datetime
from sqlalchemy import inspect
from sqlalchemy.ext.hybrid import hybrid_property
import json
class EBase:
def to_dict(self) -> {}:
dict_ = {}
for key in self.__mapper__.c.keys():
if not key.startswith('_'):
dict_[key] = getattr(self, key)
for key, prop in inspect(self.__class__).all_orm_descriptors.items():
if isinstance(prop, hybrid_property):
dict_[key] = getattr(self, key)
return dict_
def to_json(self) -> str:
return json.dumps(self.to_dict(), default=lambda o: o.strftime('%Y-%m-%d %H:%M:%S')
if isinstance(o, datetime)
else o.strftime('%Y-%m-%d')
if isinstance(o, date) else o.__dict__, indent=2)
日付と時刻を共通カラムとして持つ場合の
共通カラム基底クラス
ここで、上の EBase を継承する。
commoncolumns.py
import sqlalchemy as db
from datetime import date, datetime
from sqlalchemy import inspect
from sqlalchemy.ext.hybrid import hybrid_property
import json
class CommonColumn:
createDate = db.Column(db.DATE, name='create_date')
createTime = db.Column(db.TIMESTAMP, name='create_time', nullable=False)
def __init__(self, createDate:date, createTime:datetime):
self.createDate = createDate
self.createTime = createTime
def __repr__(self):
return f'createDate={self.createDate}, createTime={self.createTime}'
この commoncolumns.py で定義した CommonColumn を
目的のエンティティは、SQLAlchemy declarative_base と一緒に多重継承する。
テーブル名 = itemwork であるエンティティ
import sqlalchemy as db
from sqlalchemy.orm import declarative_base
from datetime import date, datetime
from commoncolumns import CommonColumn
class Twork(declarative_base(), CommonColumn):
__tablename__ = 'itemwork'
id = db.Column(db.BigInteger, nullable=False, primary_key=True)
userName = db.Column(db.String(120), name='user_name', nullable=False)
vPoint = db.Column(db.INT, name='v_point', nullable=False, default=0)
def __init__(self, id:int, userName:str, vPoint:int, createDate:date, createTime:datetime):
CommonColumn.__init__(self, createDate, createTime)
self.id = id
self.userName = userName
self.vPoint = vPoint
def __repr__(self):
return f'Twork(id={self.id}, userName={self.userName},
vPoint={self.vPoint}, {CommonColumn.__repr__(self)})'
__init__ メソッドで、CommonColumn.__init__ を実行することに注意
__repr__ メソッドで、CommonColumn.__repr__(self) の結果を反映させている。
使用例
session.query(Twork).from_statement(text(sql)).all()