2009-06-28 10 views
6

私はdjango 1.0.2(およびdjangoヘルパー)でgoogleアプリケーションエンジンを使用しています。 は、あなたがこのようなものだモデルがあるとします。Googleアプリケーションエンジンの再帰的削除

 
class Top(BaseModel): 
    pass 

class Bottom(BaseModel): 
    daddy = db.ReferenceProperty(Top) 

、私はタイプ「上部」のオブジェクトを削除するとき、私はすべての関連する「ボトム」オブジェクトも削除することにしたいです。私は「トップ」オブジェクトを削除する事が今あるとおり

、「ボトム」のオブジェクトが滞在し、私はどこにも属していないデータを取得します。ビュー内のデータストアにアクセスする場合、私はで終わる:

Caught an exception while rendering: ReferenceProperty failed to be resolved.

私はもちろん、すべてのオブジェクトを検索し、削除しますが、私の本当のモデルは深い少なくとも5つのレベルであることから、私は方法があります望んでいる可能性がありこれを自動的に行うことができるようにします。

私はそれは、Javaで動作し、それはかなり私も欲しいもののようです方法についてこのarticleを見つけました。

誰も私はdjangoで同様の動作を得ることができるか知っていますか?

答えて

6

あなたは、影響を受けたレコードを検索し、あなたが親レコードを削除すると同時に、それらを削除することによって、手動でこれを実装する必要があります。親クラスの.delete()メソッドをオーバーライドして、関連するすべてのレコードを自動的に削除することで、これを単純化することができます。パフォーマンス上の理由から

、あなたはほぼ確実に(あなたが実際のエンティティをフェッチし、デコードすることなく削除するエンティティのキ​​ーを取得することができます)、キーのみのクエリを使用すると、バッチ削除。例:

db.delete(Bottom.all(keys_only=True).filter("daddy =", top).fetch(1000)) 
+0

興味深いことに、db.deleteは各エンティティでdelete()を呼び出しますか?それは恐ろしく最適化されているので、私はあなたがこれらの2つのトリックを組み合わせることができないことを少し疑っています。しかし、keys_onlyの良い点。 –

+0

いいえ、db.delete()は、削除するすべてのキーを並列に送信する単一のRPCに直接対応します。 Entity.delete()は単にdb.delete(self)を呼び出す構文的な砂糖です。 –

+1

'db.delete(top.bottom_set)'はうまく動作しませんか? –

2

実際、その動作はGAE固有です。 DjangoのORMは.delete()の "ON DELETE CASCADE"をシミュレートします。

私はこれがあなたの質問に対する答えではないことを知っていますが、間違った場所を見るのを助けるかもしれません。

1

あなたの階層が深いレベルのごく少数である場合は、ファイルパスのように見える場で何かを行うことができるかもしれない。事の

daddy.ancestry = "greatgranddaddy/granddaddy/daddy/" 
me.ancestry = daddy.ancestry + me.uniquename + "/" 

ソート。少なくとも兄弟の間ではユニークな名前が必要です。オブジェクトIDで

パスは一種の、すでにこれを行いますが、あなたはデータドメイン内の関係を表現するために使用しないことをお勧めしているエンティティグループと密接に結びついていますIIRC。

次に、あなたはこのように、最初の部分のトリックを使用して祖父の子孫のすべてを返すようにクエリを作成することができます

query = Person.all() 
query.filter("ancestry >", gdaddy.ancestry + "\U0001") 
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF") 

もちろん、これはあなたが500バイトStringPropertyに祖先を収まらない場合は使用されません。

2

データ構造を見直してください。そして、先祖のために照会

class Top(db.Model): pass 
class Middle(db.Model): pass 
class Bottom(db.Model): pass 

top = Top() 
middles = [Middle(parent=top) for i in range(0,10)] 
bottoms = [Bottom(parent=middle) for i in range(0,10) for middle in middles] 

=トップは、すべてのレベルからすべてのレコードを検索します:関係は、レコードの有効期間に変更はありません場合は、「先祖」GAEの機能を使用することができます。だから、それは簡単に削除することができます。

descendants = list(db.Query().ancestor(top)) 
# should return [top] + middles + bottoms 
+0

美しい。リスト内包表記の使い方私は初めて2つのループを見ています!しかし、外側のループが最初に来るように、彼らは他の順序にある​​ようだ。 –

関連する問題