如何查询给定条件的先前项

时间:2017-07-19 05:43:49

标签: python django

这是模型

class Player(models.Model):
    name = models.CharField()

class ShootingAttempt(models.Model):
    player = models.ForeignKey(Player, related_name='shooting_attempts')
    is_scored = models.BooleanField()
    point = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_add_now=True)

实施:

jordan = Player.objects.create(name='Michael Jordan')

attempt1 = ShootingAttempt(player=jordan, is_scored=False)
attempt2 = ShootingAttempt(player=jordan, is_scored=False)
attempt3 = ShootingAttempt(player=jordan, is_scored=True, point=3)

attempt4 = ShootingAttempt(player=jordan, is_scored=False)
attempt5 = ShootingAttempt(player=jordan, is_scored=True, point=3)
attempt6 = ShootingAttempt(player=jordan, is_scored=True, point=3)

现在,如果给定的 ShootingAttempt ,其中pk = 5假定为名为is_scored=False的玩家,则我如何查询之前的Micheal Jordan?这将产生以下结果:[attempt4]

意味着乔丹在第5次成功挖掘3分之前有1次失误

如果给定的ShootingAttempt pk=3 (尝试3),则会返回

[attempt1, attempt2] 

意味着乔丹在成功挖掘前3分之前有2次失误

如果给出pk=6,则不会返回任何内容,因为最后 is_scored=False和{之间没有 is_scored=True {1}}(尝试6)

意味着乔丹在挖掘另外3分之前没有错过

每次尝试都可能会错过,我希望每次成功尝试都能获得最后的失误。

有什么工作吗?

3 个答案:

答案 0 :(得分:1)

这些是我更喜欢的步骤。

获取所需is_scored=True ShootingAttempt个实例的 id 。说id1

您可以使用is_scored=True获取另一个ShootingAttempt .filter(id__lt=id1).aggregate(id2=Max('id'))个实例 这将返回 {id2:some_id} ,其中is_scored=True且低于id1。

id2 = ShootingAttempt.objects.all().filter(id__lt=id1).aggregate(id2=Max('id'))['id2']

最后你可以 - .filter(id__gt=id2).filter(id__lte=id1)返回带有False s和最后True的查询集。

答案 1 :(得分:0)

您可以在查询中使用const transformData=_=>_.map(_=>Object.assign(..._.map(([$,_])=>({[$]:_})))); 。 例如:

order_by

过滤器部分选择分数为“False”的对象,然后按降序排序,最后选择第一个元素(last_false = ShootingAttempt.objects.filter(is_scored=False).order_by('-created_at')[0] )。

您还可以通过播放器以类似的方式嵌套过滤器:

[0]

编辑:

如果您希望所有以前尝试拥有该尝试的ID,您也可以last_false = ShootingAttempt.objects.filter(player=jordan).filter(is_scored=False).order_by('-created_at')[0] 使用pk进行过滤:

__lt

答案 2 :(得分:0)

解决问题。

attempts = ShootingAttempt.objects.filter(player=jordan)[:pk]
n = len(attempts)
actual_attempts = [] if attempts[n-1].is_scored == True else 
[attempts[n-1]]
n -= 1
while n and attempts[n-1].is_scored == False:
    actual_attempts.append(attempts[n-1])
    n -= 1
actual_attempts = actual_attempts[::-1]