2010-05-18 4 views
7

SQLAlchemy에서 다중 레벨 다형성을 가질 수 있습니까? 다음 예는 다음과 같습니다SQLAlchemy에서 다단계 다형성이 가능합니까?

class Entity(Base): 
    __tablename__ = 'entities' 
    id = Column(Integer, primary_key=True) 
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False) 
    entity_type = Column(Unicode(20), nullable=False) 
    __mapper_args__ = {'polymorphic_on': entity_type} 

class File(Entity): 
    __tablename__ = 'files' 
    id = Column(None, ForeignKey('entities.id'), primary_key=True) 
    filepath = Column(Unicode(255), nullable=False) 
    file_type = Column(Unicode(20), nullable=False) 
    __mapper_args__ = {'polymorphic_identity': u'file', 'polymorphic_on': file_type) 

class Image(File): 
    __mapper_args__ = {'polymorphic_identity': u'image'} 
    __tablename__ = 'images' 
    id = Column(None, ForeignKey('files.id'), primary_key=True) 
    width = Column(Integer) 
    height = Column(Integer) 

내가 Base.metadata.create_all() 전화, SQLAlchemy의 다음과 같은 오류가 발생합니다 :

IntegrityError: (IntegrityError) entities.entity_type may not be NULL`. 

이 오류가 나는 Image 모델과 Filepolymorphic_on 키를 제거하면 사라집니다.

무엇을 제공합니까?

+0

선언적 레이어가 없으면이 작업을 수행하는 것이 더 바람직 할 수 있습니다. – joeforker

답변

11

Yes. 코드의 문제는 이미지를 일종의 파일로 만들고, 트리의 헤드를 목표로 이미지를 일종의 엔티티로 만들어야한다는 것입니다.

예 : (SQL ALchemy doc 참조)

from sqlalchemy import (Table, Column, Integer, String, create_engine, 
    MetaData, ForeignKey) 
from sqlalchemy.orm import mapper, create_session 
from sqlalchemy.ext.declarative import declarative_base 

e = create_engine('sqlite:////tmp/foo.db', echo=True) 
Base = declarative_base(bind=e) 

class Employee(Base): 
    __tablename__ = 'employees' 

    employee_id = Column(Integer, primary_key=True) 
    name = Column(String(50)) 
    type = Column(String(30), nullable=False) 

    __mapper_args__ = {'polymorphic_on': type} 

    def __init__(self, name): 
     self.name = name 

class Manager(Employee): 
    __tablename__ = 'managers' 
    __mapper_args__ = {'polymorphic_identity': 'manager'} 

    employee_id = Column(Integer, ForeignKey('employees.employee_id'), 
     primary_key=True) 
    manager_data = Column(String(50)) 

    def __init__(self, name, manager_data): 
     super(Manager, self).__init__(name) 
     self.manager_data = manager_data 

class Owner(Manager): 
    __tablename__ = 'owners' 
    __mapper_args__ = {'polymorphic_identity': 'owner'} 

    employee_id = Column(Integer, ForeignKey('managers.employee_id'), 
     primary_key=True) 
    owner_secret = Column(String(50)) 

    def __init__(self, name, manager_data, owner_secret): 
     super(Owner, self).__init__(name, manager_data) 
     self.owner_secret = owner_secret 

Base.metadata.drop_all() 
Base.metadata.create_all() 

s = create_session(bind=e, autoflush=True, autocommit=False)  
o = Owner('nosklo', 'mgr001', 'ownerpwd') 
s.add(o) 
s.commit() 
0

가능하지 않음 :

Currently, only one discriminator column may be set, typically on the base-most class in the hierarchy. “Cascading” polymorphic columns are not yet supported.

그래서 당신은 당신의 유산 패턴을 변경하는 @nosklo 제안을 따라야합니다.