5

列ごとに1つの整数統計に基づいて統計を格納するモデルがあります。私は次のように、上記の統計の更新を処理するビューを持っています:

class PlayerStats(models.Model):
    #In game stats - these represent the actual keys sent by the game
    NumberOfJumps = models.IntegerField(default=0)
    NumberOfDoubleJumps = models.IntegerField(default=0)
    NumberOfSilverPickups = models.IntegerField(default=0)
    NumberOfGoldPickups = models.IntegerField(default=0)
    NumberOfHealthPickups = models.IntegerField(default=0)

私は基本的に、データベースに保存されている現在の統計に追加する必要のある統計の辞書を取得します。

可能であれば、データベースレベルでこれを実行したいので、モデルからすべてのデータを取り出してから再度更新することは本当にしたくありません。

同僚は、これをビューコードからプッシュするために、主にスレッドセーフを維持し、mysqlのデッドロックを回避するためにdjangoのF()オブジェクトを使用することを提案しました(統計テーブルは異なるスレッドによって継続的に更新される可能性があります) )。

辞書には、データベースで使用されているキーを反映したキーが含まれているため、現時点では次のようにしています。

def update_stats(new_stats):
    player_stats = PlayerStats(user=user, **new_stats)
    old_stats = player_stats.values()[0]
    updated_stats = {}
    for stat in new_stats:
        if old_stat[stat]:
            updated_stats[stat] = old_stats[stat] + new_stats[stat]
    PlayerStats.objects.filter(user=user).update(**updated_stats)

F()オブジェクトを使用してこれを実現する方法について誰かが何か指針を持っていますか?

4

2 に答える 2

4

を使用して更新するmodels.Fには、次のようなものを作成する必要があります

qs.update(field_1=models.F('field_1')+field_1_delta,
          field_2=models.F('field_2')+field_2_delta, 
          ...)

あなたのコードにとって、それはかもしれません

new_stats = {
    'NumberOfHealthPickups': 99
    # ...
}
updated_stats = {}
for stat in new_stats:
    updated_stats[stat] = models.F(stat) + new_stats[stat]
PlayerStats.objects.filter(user=user).update(**updated_stats)
于 2013-03-25T12:53:52.493 に答える
2

1つのオプションは、フィールドを1つずつ更新することです。

このコードはすべてのフィールドを一度に更新するわけではありませんが(したがって、db-accessに関しては遅い可能性があります)、安全です(デッドロックや更新の損失はありません)。

user_stats = PlayerStats.objects.get(user=user)
for stat, increment in new_stats.iteritems():
    user_stats.update(**{ stat: F(stat) + increment })
于 2013-03-25T10:55:36.147 に答える