2012-01-31 75 views
1

說我有一個SQLAlchemy的模式是這樣的:到特定的列SQLAlchemy的關係

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

class EmployeeType(Base): 
    __tablename__ = 'employee_type' 
    id = Column(Integer(), primary_key=True) 
    name = Column(String(20)) 

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer(), primary_key=True) 
    type_id = Column(Integer(), ForeignKey(EmployeeType.id)) 
    type = relationship(EmployeeType, uselist=False) 

session = Session() 
session.add(EmployeeType(name='drone')) 
session.add(EmployeeType(name='PHB')) 

我想有某種「關係」從員工直接EmployeeType.name作爲一種方便,所以我可以跳過的查找ID或EmployeeType對象的一步,如果我有一個類型名稱:

emp = Employee() 
emp.type_name = "drone" 
session.add(emp) 
session.commit() 
assert (emp.type.id == 1) 

這種事可能嗎?

編輯:我發現association_proxy可以讓我中途有:

class Employee(Base): 
    ... 
    type_name = association_proxy("type", "name") 

是,如果我分配給它的唯一問題:

emp = session.query(Employee).filter_by(EmployeeType.name=='PHB').first() 
emp.type_name = 'drone' 

它修改employee_type.name列,而不是employee.type_id列。

回答

1

我同意喬納森的一般方法,但我覺得增加僱員對象的會話,並設置員工類型應該是獨立的操作。下面是一個具有TYPE_NAME作爲一個屬性,需要設置之前,添加到會話的實現:

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

class EmployeeType(Base): 
    __tablename__ = 'employee_type' 
    id = Column(Integer(), primary_key=True) 
    name = Column(String(20)) 

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer(), primary_key=True) 
    type_id = Column(Integer(), ForeignKey(EmployeeType.id)) 
    type = relationship(EmployeeType) 

    @property 
    def type_name(self): 
     if self.type is not None: 
      return self.type.name 
     return None 

    @type_name.setter 
    def type_name(self, value): 
     if value is None: 
      self.type = None 
     else: 
      session = Session.object_session(self) 
      if session is None: 
       raise Exception("Can't set Employee type by name until added to session") 
      self.type = session.query(EmployeeType).filter_by(name=value).one() 
+0

作爲練習,我也颳起了版本,允許附加員工到會議之前設置TYPE_NAME,通過附加一個「 after_attach「事件監聽器到會話:https://gist.github.com/1750520 – 2012-02-06 07:47:45

2

我會通過創建一個方法來爲我做這個。

class EmployeeType(Base): 
    __tablename__ = 'employee_type' 
    id = Column(Integer(), primary_key=True) 
    name = Column(String(20)) 

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer(), primary_key=True) 
    type_id = Column(Integer(), ForeignKey(EmployeeType.id)) 
    type = relationship(EmployeeType, uselist=False) 

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

    def add(self, type_name=None): 
     if type_name is not None: 
      emp_type = DBSession.query(EmployeeType).filter(EmployeeType.name == type_name).first() 
      if emp_type: 
       type = emp_type 
      else: 
       type = EmployeeType(name=type_name) 
     else: 
      type = None 
     DBSession.add(Employee(type=type)) 

然後你做:

Employee.add(type_name='boss')