2015-04-22 75 views
0

我有一个字段为position = PositiveIntegerField(unique=True)的模型。给定这个模型的一个实例,我想获得下一个最高位置的实例(取决于某些过滤器)。如果这个实例是位置最高的实例,我想绕回0并返回最低位置的实例;如果这个实例是唯一的,我想返回它自己。这可以简化为单个查询吗?

这里是我的代码:

count = Player.objects.count() 
return Player.objects.filter(game_id=self.game_id, is_alive=True).annotate(
    relative_position=(F('position') - self.position - 1 + count) % count 
).order_by('relative_position')[:1].get() 

(的原因+ count是因为负数模一种积极的是SQL负)。

这需要两个数据库查询。我怀疑可以只用一个查询来完成,使用annotateCount,但我还没有弄清楚如何将这样的查询放在一起。它可以完成,如果是这样,如何?

回答

0

我发现,条件查询表达式是在Django 1.8的事情,这意味着我可以放弃模运算,并做到这一点:

return Player.objects.filter(game_id=self.game_id, is_alive=True).order_by(
    Case(When(position__gt=self.position, then=Value(0)), default=Value(1)), 
    'position' 
)[:1].get() 
0

并不总是只有一个查询,但它可能击败2个查询和注释:

players = Player.objects.filter(game_id=self.game_id, is_alive=True).order_by('position') 
try: 
    return players.filter(position__lt=self.position)[0] 
except IndexError: 
    return players.last()