继承+外键

Rhy*_*ore 5 python sql sqlalchemy flask flask-sqlalchemy

我一直在绞尽脑汁,似乎无法解决如何解决这个问题.请注意,我已从模型中删除了大量不相关的字段

我正在编写我的SQL-Alchemy模型,并遇到了以下问题:

由于多个计费系统,每个都有完全不同的属性,并且由于订阅属性的不同类型(即用户名,节点位置等),我不得不走多态继承之路.

class Subscription(Base):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    secret = db.Column(postgresql.BYTEA)
    type = db.Column(SubscriptionType.db_type())
    status = db.Column(StatusType.db_type())
    subscription_id = db.Column(db.Integer)

    __tablename__ = 'subscription'
    __table_args__ = {'schema':'public'}

    __mapper_args__ = {'polymorphic_on' : type}

    def __repr__(self):
        return '<Subscription: %r>' % self.id

class Product1(Subscription):
    __mapper_args__ = {'polymorphic_identity' : SubscriptionType.product1}    
    id = db.Column(db.Integer, db.ForeignKey('public.subscription.id'), 
        primary_key = True)
    billing_system = db.Column(
        db.Integer, 
        db.ForeignKey('public.billing_system.id')
    )

class BillingSystem(Base):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    type = db.Column(BillingSystemType.db_type())

    __tablename__ = 'billing_system'
    __table_args__ = {'schema':'public'}

    __mapper_args__ = {'polymorphic_on' : type}

    def __repr__(self):
        return '<Subscription: %r>' % self.id

class BillingSystem1(BillingSystem):
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}    
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
        primary_key = True)
    billing_system = db.Column(
        db.Integer, 
        db.ForeignKey('public.billing_system.id')
    )
    foo = db.Column(db.Integer)
    bar = db.Column(db.Integer)

 class BillingSystem2(BillingSystem):
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem2}    
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
        primary_key = True)
    billing_system = db.Column(
        db.Integer, 
        db.ForeignKey('public.billing_system.id')
    )
    bing = db.Column(db.Integer)
    boo = db.Column(db.Integer)


    __tablename__ = 'billing_system_product2'
    __table_args__ = {'schema':'public'}
Run Code Online (Sandbox Code Playgroud)

除了一件事,一切正常.

假设我运行以下内容:

>>> a = Product1()
>>> b = BillingSystem.objects.get(1)
>>> a.billing_system = b
>>> session.add(a)
>>> session.commit()
Run Code Online (Sandbox Code Playgroud)

我会收到以下错误.

sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'BillingSystem1' 'INSERT INTO
Run Code Online (Sandbox Code Playgroud)

我理解它的意思,我尝试了以下内容.

>>> a.billing_system = b.id
Run Code Online (Sandbox Code Playgroud)

这只存储ID,当我尝试检索关联的对象时,我会收到一个整数.这涉及到我不得不做一个额外的查询.我希望这不是要走的路.

我还尝试将所有计费系统ID的外键添加到Product1 Model

class BillingSystem1(BillingSystem):
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}    
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
        primary_key = True)
    billing_system = db.Column(
        db.Integer, 
        db.ForeignKey('public.billing_system.id'),
        db.ForeignKey('public.billing_system1.id'),
        db.ForeignKey('public.billing_system2.id'),
    )
    foo = db.Column(db.Integer)
    bar = db.Column(db.Integer)
Run Code Online (Sandbox Code Playgroud)

这根本不起作用,我收到了相同的ProgrammingError异常,说明该类型无法适应.

我已经搜索了手册,但找不到怎么做,但我需要某种形式的魔法选项才能实现这一点:

>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem
Run Code Online (Sandbox Code Playgroud)

代替:

>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem1
Run Code Online (Sandbox Code Playgroud)

是否有人能够阐明我如何查询我的多态模型集合中的ID,并且只获得基本模型的类?

我觉得这会解决我的问题,我只是不确定如何解决它.

感谢您花时间阅读本文,我真的想知道我哪里出错了(我也已经醒了太长时间,所以这没有帮助).

干杯,里斯

Rhy*_*ore 1

class Subscription(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    secret = db.Column(postgresql.BYTEA)
    type = db.Column(SubscriptionType.db_type())
    status = db.Column(StatusType.db_type())
    subscription_id = db.Column(db.Integer)

    billing_system_id = db.Column(
        db.Integer, 
        db.ForeignKey('public.billing_system.id')
    )
    billing_system = db.relationship('BillingSystem', backref='subscriptions')
Run Code Online (Sandbox Code Playgroud)

所以我所做的是:

1 ) 将 Subscription.billing_system_id 外键移至基本订阅模型 2) 添加到 Subscription.billing_system 关系中

所以现在我正在这样做:

>>> o = BillingSystem.query.get(1)
>>> a = Product1()
>>> a.billing_system_id = o.id
Run Code Online (Sandbox Code Playgroud)

结果是:

>>> a.billing_system.subscriptions
[<cPanel Hosting Reseller: 2>]
>>> a.billing_system_id
2
Run Code Online (Sandbox Code Playgroud)

所以除非我在这里做错了什么,否则它似乎是有效的。我只是无法传递实际的 BillingSystem 对象,实际上我必须设置 ID。不过,在保存模型时,它仍然会被引用强制执行,因此我没有看到太多问题。

感谢您的帮助 :)