想象一下,在一个人为的示例中,我有以下两个模型:
class User(models.Model):
name = models.CharField()
class Login(models.Model):
user = models.ForeignKey(User, related_name='logins')
success = models.BooleanField()
datetime = models.DateTimeField()
class Meta:
get_latest_by = 'datetime'
如何获取用户查询集,其中仅包含上次登录失败的用户。
我知道以下内容不起作用,但它说明了我想要得到的内容:
User.objects.filter(login__latest__success=False)
我猜我可以用Q对象和/或Case when,和/或其他形式的注释和过滤来做到这一点,但是我无法解决它。
答案 0 :(得分:2)
我们可以在此处使用Subquery
from django.db.models import OuterRef, Subquery
latest_login = Subquery(Login.objects.filter(
user=OuterRef('pk')
).order_by('-datetime').values('success')[:1])
User.objects.annotate(
latest_login=latest_login
).filter(latest_login=False)
这将生成如下查询:
SELECT auth_user.*, (
SELECT U0.success
FROM login U0
WHERE U0.user_id = auth_user.id
ORDER BY U0.datetime DESC
LIMIT 1
) AS latest_login
FROM auth_user
WHERE (
SELECT U0.success
FROM login U0
WHERE U0.user_id = auth_user.id
ORDER BY U0.datetime
DESC LIMIT 1
) = False
因此,Subquery
的结果是最新success
对象的Login
,如果是False
,则将相关的User
添加到QuerySet
。
答案 1 :(得分:0)
对于支票bool使用success=False
,对于最新使用latest()
您的过滤器看起来如下:
User.objects.filter(success=False).latest()
答案 2 :(得分:0)
您可以先注释最大日期,然后使用F expressions根据成功和最大日期进行过滤:
User.objects.annotate(max_date=Max('logins__datetime'))\
.filter(logins__datetime=F('max_date'), logins__success=False)