4

次のような管理アクションがあります。

def process(modeladmin, request, queryset):
    for reservation in queryset:
        if not reservation.processed:
            reservation.processed = True
            reservation.save()
            item = reservation.item
            item.available = F('available') - reservation.quantity
            item.save()

したがって、管理者は の を処理できreservationますitem。彼がそうするたびに、reservationは処理済みとしてマークされ、利用可能な数は でitems指定された数量だけ減少しますreservation

すべての管理アクションで発生するように、管理者は一度に複数の処理を行うことができますreservationsreservationsすべてが異なる場合、すべてがうまくいきitemsます。ただし、2 人reservationsが 1 人を共有しitemている場合、使用可能な数はitems、最後に処理された量で指定された分だけ減少しreservationます。

F()式はまさにこのケースのためのものだと思いました: 競合状態に陥ることなく、多くの変更を行い、属性を増減させたいのですitemitem私は何が欠けていますか?

4

2 に答える 2

0

これは実際には F オブジェクトを使用する方法ではありません。フェッチのステップを保存から分離すると、本質的に明示的に非アトミックになります。

そのために使用する必要がupdateあるため、項目部分は次のようにする必要があります。

Item.objects.filter(id=reservation.item.id).update(available=F('available')-reservation.quantity)

または似たようなもの。

于 2014-03-19T14:16:47.263 に答える
-2

F() 式は、クエリ内で使用するためのものです。たとえば、SQL でこれを実行したい場合などです。

SELECT * FROM foo WHERE foo_col = bar_col

あなたがするだろう:

Foo.objects.filter(foo_col=F('bar_col'))

いずれにせよ、最後に行われた予約に従ってアイテムを減らす必要があるという要件は、予約をループする方法を少し工夫する必要があることを意味します。1 つのオプションは、クエリセットをアイテム ID で並べ替え、ID が「変更」されるたびに、そのアイテムの最後の予約に基づいて利用可能な金額を調整することです。

于 2012-05-24T04:05:24.397 に答える