2012-03-15 10 views
1

SQLAlchemyで継承がどのように機能するかを理解するための助けが必要です。いくつかの基本的な機能を持つユーザーのための基本クラスを作成しました。そして、いくつかの特定のユーザー(admin、cooluser、uncooluser)。それぞれにユニークな機能があるので、SQLAlchemyで継承を使用することに決めました。問題は、ユーザーをcooluserまたはuncooluserにアップグレードし、いつでもcooluserをユーザーにダウングレードできることです。SQLAlchemyにおける継承の問題

class User(Base): 
    __tablename__ = 'tbl_users' 
    __table_args__ = {'mysql_engine': 'InnoDB'} 

    user_id = Column(Integer, primary_key = True, unique = True, nullable = False) 
    user_name = Column(String(100), nullable = False, unique = True) 
    password = Column(String(100), nullable = False) 
    user_type = Column('user_type', String(50)) 
    first_name = Column(String(50), nullable = False) 
    last_name = Column(String(50), nullable = False) 
    address = Column(String(50), nullable = False) 
    city = Column(String(20), nullable = False) 
    postal_code = Column(String(10), nullable = False) 
    country_id = Column(Integer, ForeignKey(Contries.country_id)) 

    country = relationship('Country', backref = 'users') 

    query = Session.query_property() 

    __mapper_args__ = {'polymorphic_on': user_type, 'polymorphic_identity': 'User'} 
class CoolUser(User): 
    __tablename__ = 'tbl_cool_user' 
    __table_args__ = {'mysql_engine': 'InnoDB'} 
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'} 

    cool_user_id = Column(Integer, ForeignKey(User.user_id, ondelete = 'CASCADE'), primary_key = True) 
    cool_user_balance = Column(Numeric(15, 3)) 

「tbl_users」に新しい行を作成せずにCoolUserを作成できますが、既存のものを使用できますか? CoolUserが削除されたときに、 'tbl_user'でなく 'tbl_user'のエントリを削除するように、いくつかの設定を変更できますか?

SQLAlchemyで継承のポイントがありませんか?

答えて

0

Concrete Table Inheritanceを使用する必要があります。ベーステーブル内のすべての共通属性はすべて、2つの異なるCoolUserおよびUnCoolUserを作成します。

+0

私はまだ混乱しています。 'User'のタイプを' CoolUser'に変更するにはどうしたらいいですか?新しい 'CoolUser'を作成すると' CoolUser'テーブルに 'User'が複製されますか? – hitripekac

+0

この例を確認し、 'polymorphic_on'を試してください。エラーが発生した場合は、そのエラーを書き込み、解決できるようにしてください。 – Nilesh

+0

特定のモデルのデータベースは既に存在し、変更することはできません。これは、接続する別のソフトウェアが既に存在するためです。私がしようとしたのは、そのモデルに準拠するようにPythonコードを作ることです。私はすべてのことを考え直さなければならないでしょう...しかし、私は助けに感謝しています。 – hitripekac

1

同じテーブルで 'polymorphic_on'と 'polymorphic_identity'を使用する必要はありません。何をする必要がある(「polymorphic_identity」で)ことからサブクラスすべてのユーザー(つまりmapper_args「polymorphic_on」が)、CoolUserを含むベーステーブルUserを作成することです:

class User(Base): 
    ... 
    __mapper_args__ = {'polymorphic_on': user_type} 

class CoolUser(User): 
    ... 
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'} 

好きなように、あなたがuser_typeを変更することができます。

+2

'User'が抽象クラスでない限り、' User'テーブルでも 'polymorhic_identity'が必要です。 – van

+0

もっと詳しい例:https://stackoverflow.com/questions/1337095/sqlalchemy-inheritance –

6

SQLAlchemyで継承のポイントがありません。

あなたは一般的にinheritanceという概念を誤って使用していると思いますが、SA実装の仕様でさえそうではありません。
古典的なAnimal (Cat, Dog (Terier))タイプの階層では、猫がのアップ/ダウングレード、あるいは特定のタイプの犬であると想像しますか?私はそうは思わない。また、CoolUserの一部も同時にAdministratorになる可能性があります。このタイプの関係をどうやって解決しますか?

したがって、要件のために、継承は、この状態変化モデルを解決するために採用する概念ではありません。私はUser-Roleの種類の関係と実装のためのGoogleにお勧めします。ロール固有のデータを格納するという問題を解決する必要があります。 @aquavitaeとして


述べた:SAで、あなたの周り-ハックとuser_typeを変更することができます。しかし、この場合には、以下が起こることに注意してください:

  • あなたは、データベースからオブジェクトをロードするときにCoolUserからユーザーにオブジェクトを(ダウングレードすると、そのクラスは、新しいタイプ(GOOD)
  • を反映します)、CoolUserに対応する行は削除されません(私はそれは悪いと思うかもしれませんが、OKかもしれません)
  • あなたはCoolUserテーブルのためのオブジェクトを(ユーザーからCoolUser)作成され、すべての値がNULLになります。したがって、作成されていない行に格納されているプロパティを設定/追加すると、エラーが発生します。特定のサブクラスのクエリでは、ではないはオブジェクトを取得するためにINNER JOINが使用されるため、オブジェクトを戻します。 (悪い)
  • 要約すると、犬に猫を変更しないでください
+2

+1私は私の答えにあまりにも注意を払う必要があります!このユースケースでは、ユーザーがフィルタを使用してクエリを実行する方がよいでしょう。 – aquavitae

+1

ありがとうございます。私は全体を再考する必要がありますね。継承がサブテーブルになると思った理由は、すべてのユーザ( 'CoolUser'、' UnCoolUser'、 'Admin')はログイン、ログアウトなどが必要だからです。しかし、私は間違っていたと思います... – hitripekac

+0

ログイン指向のタスク( 'User'と呼ぶ)のための別のテーブルを作成し、階層を作成することをお勧めします(' Person( - > CoolPerson、 - > UncoolPerson、 - > Distributor ) ')を実行してから、' Person.user_id'(あなたは同じID値を使うことさえできます)に外部キーを持っています。この場合、 'Administrator'はおそらく' role'(または 'User'テーブルのただのフラグ)であり、' Person'とその子孫について何も知らずに 'User'テーブルにのみ関連します。 – van