【问题标题】:sqlAlchemy, concrete inheritance, but parent has foreignKeysqlAlchemy,具体继承,但父级有foreignKey
【发布时间】:2021-11-09 12:06:20
【问题描述】:

我有 3 个班级:

  • 用户
  • 员工
  • 经理

Manager 继承自 Employee。用户表不与继承相关。

到目前为止一切顺利:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    email = Column(String(255))

class Employee(AbstractConcreteBase, Base):
    name = Column(String(30))

class Manager(Employee):
    __tablename__ = 'manager'
    employee_id = Column(Integer, primary_key=True)
    dept = Column(String(30))
    __mapper_args__ = {'polymorphic_identity':'manager', 'concrete':True}

它创建了我想要的用户和管理器。

但是,

如果我们在父类中引入一个 ForeignKey,上述中断:

class Employee(AbstractConcreteBase, Base):
    name = Column(String(30))
    user_id = Column(Integer, ForeignKey('user.id'))        

错误是:

sqlalchemy.exc.InvalidRequestError:

Columns with foreign keys to other columns must be declared as @declared_attr callables on declarative mixin classes.

到目前为止,我还不懂the mixin docs (link)

在我的基类(在本例中为员工)中允许外键需要什么?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    你可以像这样使用 mixin:

    from sqlalchemy import *
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.ext.declarative import declared_attr
    
    
    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer, primary_key=True)
        email = Column(String(255))
    
    class Employee(object):
        name = Column(String(30))
        @declared_attr
        def user_id(cls):
            return Column(Integer, ForeignKey('user.id'))
    
    class Manager(Base, Employee):
        __tablename__ = 'manager'
        employee_id = Column(Integer, primary_key=True)
        dept = Column(String(30))
        __mapper_args__ = {'polymorphic_identity':'manager', 'concrete':True}
    

    参考:Mixing in Columns

    【讨论】:

    • 为什么这个答案不被接受? @declared_attr 是正确的选择。
    • 在这种情况下如何设置 user_id? manager = Manager() 然后manager.user_id = 2 将不起作用.. 你绝对需要使用同义词和 getter/setter 吗?
    【解决方案2】:

    Mixin class 是您可以将共享功能放入(例如公共列、公共表选项...等)的地方,然后让其他具体(子)类通过继承来重用 mixin 中的代码。 Mixin 类本身不是 ORM 映射类,迁移后不会生成数据库表。

    在最新版本的 SQLAlchemy(1.4.26,截至撰写此答案时),如果您的 mixin 类不包含外键约束,则不需要 declared_attr 来声明公共字段或继承 Base类。

    代码如下:

    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer, primary_key=True)
        email = Column(String(255))
    
    class EmployeeMixin: # Mixin class
        name = Column(String(30))
    
    class Manager(Base, EmployeeMixin):
        # will copy `name` column from EmployeeMixin to this class once migrated
        __tablename__ = 'manager'
        employee_id = Column(Integer, primary_key=True)
        dept = Column(String(30))
        __mapper_args__ = {'polymorphic_identity':'manager', 'concrete':True}
    

    【讨论】:

      猜你喜欢
      • 2017-02-15
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 2014-09-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      相关资源
      最近更新 更多