【发布时间】:2017-11-04 01:36:33
【问题描述】:
在为某个方法编写测试用例时,我发现使用 my_queryset.first().my_annotated_value 与使用 my_queryset.last().my_annotated_value 时得到的结果不同,尽管 my_queryset.count() 返回 1。
这里是相关代码sn-p:
class ShopManager(models.Manager):
def get_best_matches(self, customer):
shops = super(ShopManager, self).get_queryset().filter(employees__matches__customer=customer).annotate(max_match_percentage=Coalesce(Max('employees__matches__match_value'), 0)).order_by('-max_match_percentage')
for shop in shops:
shop.max_match_percentage = float(shop.max_match_percentage) * 100.0
return shops
在我运行的 shell 中:
shops = Shop.objects.get_best_matches(customer=Customer_A)
shops.count() # returns 1
shops.first().max_match_percentage # returns 73.9843
shops.last().max_match_percentage # returns Decimal('0.739843')
我有 shops、matches、employees 和 customers 的不同 django 应用程序。
我搜索了几个小时并检查了 django 文档中 first() 和 last() 的实现。我找不到任何可以解释这种行为的东西。
为什么值不同,到底发生了什么?我做错了什么还是这是一个错误?
【问题讨论】:
-
您可以尝试以相反的顺序运行
shops.first().max_match_percentage和shops.last().max_match_percentage。结果是什么 -
@Tushortz 我刚试过,结果是一样的。
shop.last().max_match_percentage仍然返回Decimal('0.739843')和shop.first().max_match_percentage仍然返回73.9843 -
您遇到了数据一致性问题。调用
last时再次克隆查询集,它不会在管理器方法中运行for循环,因此您看到的是数据库中的当前值。请参阅 Alasdair 的回答。 -
尽量不要在管理器中评估查询集。经理应该从数据库中检索数据,而不是更改它们。
标签: python django python-2.7 django-annotate