8

次の宇宙征服ゲームの models.py のスケルトンを考えてみましょう:

class Fleet(models.Model):
    game = models.ForeignKey(Game, related_name='planet_set')
    owner = models.ForeignKey(User, related_name='planet_set', null=True, blank=True)
    home = models.ForeignKey(Planet, related_name='departing_fleet_set')
    dest = models.ForeignKey(Planet, related_name='arriving_fleet_set')
    ships = models.IntegerField()

class Planet(models.Model):
    game = models.ForeignKey(Game, related_name='planet_set')
    owner = models.ForeignKey(User, related_name='planet_set', null=True, blank=True)
    name = models.CharField(max_length=250)
    ships = models.IntegerField()

私が取り組んでいるプロジェクトには、このようなデータ モデルが多数あり、さまざまなデータ オブジェクト間のやや複雑な相互作用に基づいてゲームの状態を変更します。データベースへの多くの不要な呼び出しを避けたいので、1ターンに1回、次のようにします

  1. データベースからすべての艦隊、惑星、およびその他のオブジェクトを照会し、それらを Python オブジェクトとしてキャッシュします
  2. ゲームオブジェクトを処理し、ゲームの状態を解決する
  3. それらをデータベースに保存します

このモデルは、ForeignKey オブジェクトを使用すると完全に崩壊するようです。たとえば、新しい艦隊が惑星を出発するとき、次のような行があります。

fleet.home.ships -= fleet.ships

この行が実行された後、惑星の艦隊を含む各惑星の船の数を変更する他のコードがあります。残念ながら、上記の行で行った変更は、以前に取得した惑星の QuerySet には反映されていないため、ターンの終わりにすべての惑星を保存すると、fleet.home の船への変更が上書きされます。

この状況を処理するためのより良い方法はありますか? それとも、これがすべての ORM のあり方ですか?

4

2 に答える 2

20

Django の ORM はID マップを実装していません(これはチケット トラッカーにありますが、実装されるかどうか、いつ実装されるかは明らかではありません。少なくとも 1 人のコア Django コミッターが反対を表明しています)。これは、2 つの異なるクエリ パスを介して同じデータベース オブジェクトに到達した場合、メモリ内の異なる Python オブジェクトを操作していることを意味します。

これは、Django ORM を使用して設計 (一度にすべてをメモリにロードし、多くの変更を加え、最後にすべてを保存する) が機能しないことを意味します。1 つ目は、同じオブジェクトの複製コピーで大量のメモリの読み込みを浪費することが多いためです。2 つ目は、実行中のような「上書き」の問題のためです。

これらの問題を回避するには、設計をやり直す必要があります (一度に 1 つの QuerySet だけで作業し、別のクエリを作成する前に変更したものをすべて保存するように注意するか、複数のクエリをロードする場合は、すべての関係を手動で調べてください。便利な属性を使用して ForeignKey をトラバースするか、ID マップを実装する代替の Python ORM を使用します。 SQLAlchemyは 1 つのオプションです。

これは、Django の ORM が「悪い」という意味ではないことに注意してください。この種の問題がまれな Web アプリケーションの場合に最適化されています (私は何年も Django を使用して Web 開発を行ってきましたが、実際のプロジェクトでこの問題が発生したことは一度もありません)。ユース ケースが異なる場合は、別の ORM を選択することをお勧めします。

于 2009-03-25T15:16:03.853 に答える
1

これはおそらくあなたが探しているものです:

https://web.archive.org/web/20121126091406/http://simonwillison.net/2009/May/7/mmalones/

于 2009-05-22T14:34:54.950 に答える