2016-12-27 66 views
0

比方說,我們有幾個SQLAlchemy的模型目錄:自動化SQLAlchemy的聲明模型創建

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import Column, Integer 
from sqlalchemy.orm import relationship 
Base = declarative_base() 

class Plane(Base): 
    __tablename__ = 'Plane' 
    plane_id = Column(Integer, primary_key=True) 

class Car(Base): 
    __tablename__ = 'Car' 
    car_id = Column(Integer, primary_key=True) 

現在對於我們想這些涉及到外部IDS進口/出口的目的。因此,對於Plane,我們可以這樣寫:

class PlaneID(Base): 
    issuer = Column(String(32), primary_key=True) 
    external_id = Column(String(16), primary_key=True) 

    plane_id = Column(Integer, ForeignKey(Plane.plane_id)) 
    plane = relationship(Plane, backref='external_ids') 

一個CarID模型將在完全相同的方式來定義。

有什麼可能使這個過程自動化?

也許我們可以使用mixin,factory,decorator或meta class。那麼我們將如何生成動態命名的列呢?能夠根據需要爲生成的模型添加更多的列將是一件好事。例如:

class CarID(ExternalID): 
    valid_from = Column(Date) 

回答

1

你也可以繼承DeclarativeMeta - 在declarative_base功能使用的元類:

from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base 
from sqlalchemy import Column, Integer, String, ForeignKey 
from sqlalchemy.orm import relationship 

class ExternalObject(DeclarativeMeta): 
    def __new__(mcs, name, bases, attributes): 
     if 'issuer' not in attributes: 
      attributes['issuer'] = Column(String(32), primary_key=True) 
     if 'external_id' not in attributes: 
      attributes['external_id'] = Column(String(16), primary_key=True) 
     if name[-2:] == 'ID': 
      ext_cls_name = name[:-2] 
      attr_rel = ext_cls_name.lower() 
      attr_id = '%s_id' % attr_rel 
      if attr_rel in attributes or attr_id in attributes: 
       # Some code here in case 'car' or 'car_id' attribute is defined in new class 
       pass 
      attributes[attr_id] = Column(Integer, ForeignKey('%s.%s' % (ext_cls_name, attr_id))) 
      attributes[attr_rel] = relationship(ext_cls_name, backref='external_ids') 
     new_cls = super().__new__(mcs, name, bases, attributes) 
     return new_cls 

ExternalID = declarative_base(metaclass=ExternalObject) 

之後,你可以從ExternalID創建子類,像你這樣爲CarID添加其他屬性。

+0

那麼,我將不得不將所有的模型都放在'ExternalID'上,我不會嗎? – bodo

+0

@canaaerus是的,這是正確的。 –