2017-02-08 10 views
0

sqlalchemyに自己参照関係がありますが、その例は大きく分けてin this answerです。sqlalchemyアソシエーションプロキシで適切にカスケード削除

私はユーザのテーブルと、プライマリユーザをセカンダリユーザにリンクさせるアソシエーションテーブルを持っています。ユーザーAはユーザーBのプライマリになることができ、BはユーザーAのプライマリになることもあれば、そうでないこともあります。

これはうまく動作しますが、アソシエーションプロキシのカスケードルールを確立する方法はわかりません。現在、ユーザーを削除すると、関連付けレコードは残っていますが、削除されたユーザーにはFKがNULLになりません。私は関連テーブルにカスケードし、レコードを削除する削除します。

また、ユーザーの関連付けレコードを削除するだけで、ユーザーの "is_primary_of"および "is_secondary_of"関連付けプロキシに伝播するユーザーの関連付けを解除できる必要があります。

私が持っているモデルにこれらの振る舞いを統合する方法を知る手助けがありますか?コードは以下のとおりです。ありがとう!

import sqlalchemy 
import sqlalchemy.orm 
import sqlalchemy.ext.declarative 
import sqlalchemy.ext.associationproxy 


# This is the base class from which all sqlalchemy table objects must inherit 
SAModelBase = sqlalchemy.ext.declarative.declarative_base() 


class UserAssociation(SAModelBase): 
    __tablename__ = 'user_associations' 

    # Columns 
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) 

    # Foreign key columns 
    primary_user_id = sqlalchemy.Column(sqlalchemy.Integer, 
            sqlalchemy.ForeignKey('users.id', name='user_association_primary_user_fk')) 
    secondary_user_id = sqlalchemy.Column(sqlalchemy.Integer, 
             sqlalchemy.ForeignKey('users.id', name='user_association_secondary_user_fk')) 

    # Foreign key relationships 
    primary_user = sqlalchemy.orm.relationship('User', 
              foreign_keys=primary_user_id, 
              backref='secondary_users') 
    secondary_user = sqlalchemy.orm.relationship('User', 
              foreign_keys=secondary_user_id, 
              backref='primary_users') 

    def __init__(self, primary, secondary, **kwargs): 
     self.primary_user = primary 
     self.secondary_user = secondary 
     for kw,arg in kwargs.items(): 
      setattr(self, kw, arg) 


class User(SAModelBase): 
    __tablename__ = 'users' 

    # Columns 
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) 
    first_name = sqlalchemy.Column(sqlalchemy.String) 
    last_name = sqlalchemy.Column(sqlalchemy.String) 

    is_primary_of = sqlalchemy.ext.associationproxy.association_proxy('secondary_users', 'secondary_user') 
    is_secondary_of = sqlalchemy.ext.associationproxy.association_proxy('primary_users', 'primary_user') 

    def associate(self, user, **kwargs): 
     UserAssociation(primary=self, secondary=user, **kwargs) 

答えて

2

非常に簡単です。元のコードの後方参照は単なる文字列でしたが、代わりにバックリファレンスオブジェクトにすることができます。これにより、カスケード動作を設定できます。 sqlalchemy documentation on backref argumentsを参照してください。

ここで必要な変更は、UserAssociationオブジェクトのみです。

# Foreign key columns 
primary_user_id = sqlalchemy.Column(sqlalchemy.Integer, 
            sqlalchemy.ForeignKey('users.id', 
                  name='user_association_primary_user_fk'), 
            nullable=False) 
secondary_user_id = sqlalchemy.Column(sqlalchemy.Integer, 
             sqlalchemy.ForeignKey('users.id', 
                  name='user_association_associated_user_fk'), 
             nullable=False) 

# Foreign key relationships 
primary_user = sqlalchemy.orm.relationship('User', 
              foreign_keys=primary_user_id, 
              backref=sqlalchemy.orm.backref('secondary_users', 
                      cascade='all, delete-orphan')) 
secondary_user = sqlalchemy.orm.relationship('User', 
              foreign_keys=secondary_user_id, 
              backref=sqlalchemy.orm.backref('primary_users', 
                      cascade='all, delete-orphan')) 

backrefキーワードの引数は、文字列ではなくバックリファレンスオブジェクトになりました。また、外部キー列をnullにできないようにすることもできました。なぜなら、削除されたユーザーをカスケードして、関連付けも削除されるからです。

関連する問題