5

私はこれについて絶対に頭を悩ませてきました、そして問題を回避する方法を理解することができないようです。モデルから無関係なフィールドをたくさん切り取ったことに注意してください

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'}

1つを除いて、すべて正常に機能しています。

次のコマンドを実行するとします。

>>> a = Product1()
>>> b = BillingSystem.objects.get(1)
>>> a.billing_system = b
>>> session.add(a)
>>> session.commit()

次のエラーが発生します。

sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'BillingSystem1' 'INSERT INTO

私はそれが何を言っているのか理解しており、私は次のことを試みました。

>>> a.billing_system = b.id

これはIDのみを格納し、関連付けられたオブジェクトを取得しようとすると、代わりに整数を受け取ります。これには、追加のクエリを実行する必要があります。私はこれが行く方法ではないと思います。

また、すべての課金システムIDの外部キーをProduct1モデルに追加してみました

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)

これもまったく機能せず、型が適応できないことを示す同じProgrammingError例外を受け取りました。

マニュアルをトロールしましたが、その方法がわかりませんが、これを実現するには、なんらかの魔法のオプションが必要です。

>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem

それ以外の:

>>> a = BillingSystem.query.get(1)
>>> type(a)
BillingSystem1

ポリモーフィックモデルのセットにIDを照会し、ベースモデルのクラスのみを取得する方法に光を当てることができる人はいますか?

私はこれが私の問題を解決するだろうと感じています、私はそれをどのように解決するのかよくわかりません。

これを読んでくれてありがとう、そして私は本当に私がどこで間違っているのかを知りたいです(私もあまりにも長い間起きていたので、それは助けにはなりません)。

乾杯、リス

4

1 に答える 1

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')

だから私がやったことは次のとおりです。

1) Subscription.billing_system_id 外部キーをベース サブスクリプション モデルにシフト 2) Subscription.billing_system 関係に追加

だから今私はこれをやっています:

>>> o = BillingSystem.query.get(1)
>>> a = Product1()
>>> a.billing_system_id = o.id

結果は次のとおりです。

>>> a.billing_system.subscriptions
[<cPanel Hosting Reseller: 2>]
>>> a.billing_system_id
2

したがって、ここで何か間違ったことをしていない限り、うまくいくようです。実際の BillingSystem オブジェクトを渡すことができず、実際に ID を設定する必要があります。ただし、モデルが保存されるときに参照が強制されるため、あまり問題はありません。

ご協力いただきありがとうございます :)

于 2012-06-06T02:58:55.340 に答える