SqlAlchemy 与特定列的关系

Mu *_*ind 6 python sqlalchemy foreign-key-relationship

假设我有一个像这样的 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'))
Run Code Online (Sandbox Code Playgroud)

为了方便起见,我希望从 Employee 直接与 EmployeeType.name 建立某种“关系”,因此如果我有类型名称,我可以跳过查找 id 或 EmployeeType 对象的步骤:

emp = Employee()
emp.type_name = "drone"
session.add(emp)
session.commit()
assert (emp.type.id == 1)
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

编辑:我发现association_proxy可以让我在那里中途:

class Employee(Base):
    ...
    type_name = association_proxy("type", "name")
Run Code Online (Sandbox Code Playgroud)

唯一的问题是,如果我分配给它:

emp = session.query(Employee).filter_by(EmployeeType.name=='PHB').first()
emp.type_name = 'drone'
Run Code Online (Sandbox Code Playgroud)

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

Mu *_*ind 4

我同意Jonathan的一般做法,但我觉得向会话中添加员工对象并设置员工类型应该是独立操作。这是一个以 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()
Run Code Online (Sandbox Code Playgroud)