私は次の関数を書きました:
def auto_update_ratings(amounts, assessment_entries_qs, lowest_rating=-1):
start = 0
rating = lowest_rating
ids = assessment_entries_qs.values_list('id', flat=True)
for i in ids: # I have absolutely no idea why this seems to be required:
pass # without this loop, the last AssessmentEntries fail to update
# in the following for loop.
for amount in amounts:
end_mark = start + amount
entries = ids[start:end_mark]
a = assessment_entries_qs.filter(id__in=entries).update(rating=rating)
start = end_mark
rating += 1
これは、想定されていることを実行します (つまり、 で指定されているようにassessment_entries_qs
、各評価 ( から始まる) で関連する数のエントリを更新します)。簡単な例を次に示します。lowest_rating
amounts
>>> assessment_entries = AssessmentEntry.objects.all()
>>> print [ae.rating for ae in assessment_entries]
[None, None, None, None, None, None, None, None, None, None]
>>>
>>> auto_update_ratings((2,4,3,1), assessment_entries, 1)
>>> print [ae.rating for ae in assessment_entries]
[1, 1, 2, 2, 2, 2, 3, 3, 3, 4]
ids
ただし、 を反復する前に反復しない場合amounts
、関数はクエリセットのサブセットのみを更新します。現在のテスト データ (クエリセットの約 250 AssessmentEntries
) では、常に正確に 84AssessmentEntries
が更新されません。
興味深いことに、更新を行わないのは常に 2 番目の for ループの最後の反復 (ただし、その反復の残りのコードは適切に実行されます)と、前の反復の一部です。クエリセットは、この関数に渡される前に、ordered_by('?') であり、以前の「空の」for ループを追加するだけで意図した結果が得られるため、データの問題ではないようです)。
関連があることが判明した場合に備えて、さらにいくつかの詳細を示します。
AssessmentEntry.rating
が目安IntegerField(null=True,blank=True)
です。- この関数は純粋にテスト目的で使用しているため、iPython からのみ実行しています。
- テスト データベースは SQLite です。
質問:ids
実際にはデータにまったく触れていないにもかかわらず、を反復処理する必要があるように見える理由と、そうしないと関数が (ある程度) 正しく実行されるのに、最後のいくつかの項目の更新に常に失敗する理由を説明してくださいどうやらまだそれらを繰り返しているにもかかわらず、クエリセット?