0

いくつかのアイテムを持ついくつかのグループがあるとします。グループ内でアイテムに一意のインデックスを付けたい:

class Item(models.Model):
    group = models.ForeignKey(Group, null=True)
    index = models.IntegerField(default=0)

    class Meta:
        unique_together=('group','index')

    def save(self):
        if self.pk is None and self.group_id is not None:
            self.thread_index = Item.objects.filter(group_id=group_id).count()+1
        return super(Item, self).save()

しかし、更新はアトミックではないため、これには問題があります。つまり、thread_index を計算した後、データベースに書き込む前に、別のトランザクションが別の行を追加した可能性があります。

IntegrityError をキャッチして再試行することで動作させることができることを理解しています。しかし、次のようなSQLを使用して、挿入コマンドの一部としてアトミックにデータを入力する良い方法があるかどうか疑問に思います。

insert into app_item (group, index) 
select 25, count(*) from app_item where group_id=25
4

2 に答える 2

0

考えられる解決策の 1 つは、シグナルまたはカスタム保存アプローチに問題がある場合indexプロパティ フィールドを作成して実行時に計算することです。

class Item(models.Model):
  group = models.ForeignKey(Group, null=True)

def _get_index(self):
  "Returns the index of groups"
   return Item.objects.filter(group_id=group_id).count()+1
index = property(_get_index)

モデルindexのフィールドとして使用するようになりました。Item

于 2012-07-27T06:46:46.410 に答える
0

django モデルを使用しているため、特に指定しない限り、インデックス フィールドを追加すると、すべてのモデルに追加された主キーに対して何が得られますか? オブジェクトを削除するときにまだ問題となる連続したインデックスを持つアイテムが必要でない限り、 id フィールドは、概説したように要件を確実に満たしているように見えます。

このフィールドが必要な場合は、信号を利用するオプションがあります。オブジェクトの post_save シグナルのレシーバーを作成すると、おそらくそれを処理できます。

于 2012-07-27T00:22:24.917 に答える