2012-04-13 18 views
2

カテゴリが削除されたときに製品category_idをデフォルト値に自動設定するにはどうすればよいですか?たとえば、最初のカテゴリを指す1削除時に外部キーをデフォルト値に設定するにはどうすればよいですか?

class Product(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(80)) 
    content = db.Column(db.Text(), unique=True) 
    category_id = db.Column(db.Integer, db.ForeignKey('category.id')) 
    atime = db.Column(db.DateTime()) 

    def __init__(self, name, content, category_id): 
     self.name = name 
     self.content = content 
     self.category_id = category_id 
     self.atime = datetime.now() 

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

class Category(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(80)) 
    products = db.relationship('Product', backref='category', cascade="all, delete, delete-orphan") 

    def __init__(self, *args, **kwargs): 
     if len(kwargs) > 0: 
      self.name = kwargs['name'] 

    def __repr__(self): 
     return '<Category %r>' % self.name 

私はそれらを削除するために、カスケードを使用したくありません!

答えて

6

ここでオーケストレーションで実行する必要が二つあります。

  1. は私が考えて、適切な参照アクション
  2. 設定でSA関係

のカスケードオプションを外部キーを定義カテゴリが削除されたときにcategory_idNULLの値に設定するのが最も簡単です。​​は、句の可能なReferential Actionsの1つです.wあなたはオプションSET DEFAULTを使用することができます同様に

category_id = db.Column(db.Integer, db.ForeignKey('category.id', ondelete='SET NULL')) 

を、この場合には、あなたはまた、カラムcategory_idのデフォルト値を設定する必要があります:HICHあなたのForeignKey定義に追加することができますcategory_id = Column(..., server_default=1)。異なるRDBMS間では、これらの実装が異なります。

cascadeオプションについて:基本的には、products関係定義からcascade="all, delete, delete-orphan"を削除する必要があります。実際には、delete, delete-orphanが存在しないようにする必要があります。

# scenario-1: delete in session: SA might set category_id of all chilren Products to None 
c1 = session.query(Category).get(1) 
session.delete(c1) 
session.commit() 

# scenario-2: delete without loading an object into the session: SA will perform no additional logic 
session.query(Category).filter(Category.id == 2).delete() 
session.commit() 

希望このすべてを:

は、あなたが本当にあなたのRDBMSとSAの構成に応じて異なる結果が生じる可能性がありますCategoryオブジェクトの二つの異なる欠失など、さまざまなシナリオをカバーするためにあなたのコードをテストする必要があると述べましたあなたを正しい方向に向ける。いつものように、echo=Trueを使って、あるいはloggingモジュールを設定するだけで、テストコードのSQLログを有効にすると、あなたのデータベースが何をしているのかがわかります。 SQLで表示されなかったその他の変更は、参照アクションを指定してRDBMS自体によって行われました。

関連する問題