我写了以下函数:
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
),它总是导致正好 84个AssessmentEntries
没有被更新。
有趣的是,它始终是第二个 for 循环的最后一次迭代,它不会导致任何更新(尽管该迭代中的其余代码确实执行正确),以及前一次迭代的一部分。查询集在传递给此函数之前是ordered_by('?'),如果我简单地添加前面的“空”for循环,就可以达到预期的结果,所以我的数据似乎没有问题)。
更多细节,以防万一它们被证明是相关的:
AssessmentEntry.rating
是一个标准IntegerField(null=True,blank=True)
。- 我使用这个函数纯粹是为了测试目的,所以我只从 iPython 执行它。
- 测试数据库是 SQLite。
问题:有人可以解释为什么我似乎需要迭代ids
,尽管实际上没有以任何方式接触数据,以及为什么不这样做,函数仍然(有点)正确执行,但总是无法更新最后几项尽管显然仍在迭代它们,但查询集?