2017-02-17 41 views
1

我是使用SQLAlchemy創建ORM的新手,我僅用於使用原始SQL。我有數據庫表,LabelPosition,並且DataSet類似以下內容:如何在SQLAlchemy中合併兩個模型類

enter image description here

以及相應的Python類如下:

class Label(Base): 
    __tablename__ = 'Label' 

    id = Column(Integer, primary_key=True) 
    name = Column(String, nullable=False, unique=true) 


class Position(Base): 
    __tablename__ = 'Position' 

    id = Column(Integer, primary_key=True) 
    name = Column(String, nullable=False, unique=true) 


class DataSet(Base): 
    __tablename__ = 'DataSet' 

    id = Column(Integer, primary_key=True) 
    label_id = Column(Integer, ForeignKey('Label.id')) 
    position_id = Column(Integer, ForeignKey('Position.id')) 
    timestamp = Column(Integer, nullable=False) 

但在我役,我不揭露那些label_idposition_id。所以我做了一個新的課Data作爲字符串持有0​​和position

# Not a full class to only show my concept 
class Data: 
    # data dictionary will have data 
    def __init__(self, **kwargs): 
     # So it doesn't have ids. Label and Position as string 
     keys = {'label', 'position', 'timestamp'} 
     self.data = {k: kwargs[k] for k in keys} 

    # An example of inserting data. 
    # skipped detail and error handling to clarify 
    def insert(self): 
     session = Session() 
     # get id of label and position 
     # remember that it returns a tuple, not a single value 
     self.data['label_id'] = session.query(Label.id).\ 
      filter(Label.name == self.data['label']).one_or_none() 
     self.data['position_id'] = session.query(Position.id).\ 
      filter(Position.name == self.data['position']).one_or_none() 
     # add new dataset 
     self.data.pop('label') 
     self.data.pop('position') 
     new_data = DataSet(**self.data) 
     session.add(new_data) 
     session.commit() 

但它看起來有點難看,我認爲應該有一個更簡單的方法來做到這一點。有什麼辦法可以使用SQLAlchemy API來組合這些表類嗎?

回答

1

您可以使用relationshipsassociation proxies使從DataSet鏈接LabelPosition對象:

from sqlalchemy.orm import relationship 
from sqlalchemy.ext.associationproxy import association_proxy 

class DataSet(Base): 
    __tablename__ = 'DataSet' 

    id = Column(Integer, primary_key=True) 

    label_id = Column(Integer, ForeignKey('Label.id')) 
    label = relationship('Label') 
    label_name = association_proxy('label', 'name') 

    position_id = Column(Integer, ForeignKey('Position.id')) 
    position = relationship('Position') 
    position_name = association_proxy('position', 'name') 

    timestamp = Column(Integer, nullable=False) 

這之後,您可以訪問LabelPosition通過新屬性鏈接到DataSet(他們的名字)對象:

>>> d = session.query(DataSet).first() 
>>> d.position 
<Position object at 0x7f3021a9ed30> 
>>> d.position_name 
'position1' 

插入DataSet對象不是這樣美麗不幸。您可以指定creator功能association_proxy可以得到一個名字,並創建或檢索相應的對象(在this answer找到):

def _label_creator(name): 
    session = Session() 
    label = session.query(Label).filter_by(name=name).first() 
    if not label: 
     label = Label(name=name) 
     session.add(label) 
     session.commit() 
    session.close() 
    return label 

label_name = association_proxy('label', 'name', creator=_label_creator) 

指定了兩個代理服務器creator功能後,您可以創建新的DataSet對象是這樣的:

dataset = DataSet(
    label_name='label1', 
    position_name='position2', 
    timestamp=datetime.datetime.now() 
) 
+0

我剛剛閱讀了關於關係,但不知道關聯代理。這將節省我的時間。非常感謝你! –

相關問題