自动化sqlalchemy声明模型创建

时间:2016-12-27 13:46:01

标签: python sqlalchemy

假设我们有几个sqlalchemy模型用于目录:

Plane

现在出于导入/导出目的,我们希望将这些与外部ID相关联。因此对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

class CarID(ExternalID): valid_from = Column(Date) 模型将以完全相同的方式定义。

自动执行此流程有哪些可能性?

也许我们可以使用mixin,factory,decorator或meta class。那么我们如何生成动态命名的Columns呢?能够根据需要向生成的模型添加更多列将是一件好事。例如:

public abstract class Character{
    private double damage;
    public Character();
    public void setDamage(damage){
         this.damage = damage;
    }
    public double getDamage(){return damage;}

}


public class Human extends Character{
    public Human(){
        damage = 10.00;
    }
}


public abstract class Object extends Character{
    public abstract String getDescription();
}


public class Sword extends Object{
    Character character;

    public Sword(Character character){
        this.character = character;
        updateDamage();
    }
    public String getDescription(){
          // Something
    }

    public void updateDamage(){
         character.setDamage(character.getDamage() + 2.00);
    }
}

1 个答案:

答案 0 :(得分: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所做的其他属性。