有关背景,请参阅此问题:Returning the current project status (i.e., most recent date on Django ManyToMany relationship)
当我在思考这个问题时,它引发了一个我自己的问题。基本上,你有类似于以下内容的东西:
class StatusType(models.Model):
name = models.CharField(max_length=64)
class Project(models.Model):
status = models.ManyToManyField(StatusType, through='ProjectStatusType')
class ProjectStatusType(models.Model):
project = models.ForeignKey(Project)
status_type = models.ForeignKey(StatusType)
created = models.DateTimeField(auto_now_add=True)
要获取特定项目的当前状态类型,您可以执行以下操作:
Project.status.order_by('-projectstatustype__created')[0]
但是如果你想获得当前状态为'foo'的所有项目怎么办?
Project.objects.filter(status__name='foo')
这将返回曾经拥有'foo'状态的项目,无论它是否是当前状态。你几乎想做类似的事情(注意在过滤器中使用current
):
Project.objects.annotate(current=Max('projectstatustype__created')).filter(status__name='foo', projectstatustype__created=current)
显然,这不起作用,因为在那个上下文中,current
应该是当前范围内的Python变量,但它让我感到疑惑:是否有某种方法可以将相同的概念传递给SQL,它会查找与刚刚创建的注释匹配的创建日期吗?
更新:
@akonsu建议简单地使用ProjectStatusType
模型。然而,这并没有真正解决任何问题。
ProjectStatusType.objects.filter(statustype__name='foo')
返回状态为“foo”的所有ProjectStatusType
。然后,您可以遍历查询集并使用Project
属性获取每个project
,但同样,这些项目将在某个时间点具有此状态,不一定是具有此状态的项目目前。即使你尝试过类似的东西:
ProjectStatusType.objects.filter(statustype__name='foo').order_by('-created')[0]
然后访问project
属性,这只会为您提供最近收到此状态的项目,而不是所有当前具有该状态的项目。
答案 0 :(得分:4)
基本上问题是如何通过比较两个字段来过滤查询集:https://docs.djangoproject.com/en/dev/topics/db/queries/#filters-can-reference-fields-on-the-model。
因此可以修复使用注释的原始查询:
Project.objects.annotate(current=Max('projectstatustype__created'))
.filter(status__name='foo',
projectstatustype__created=F('current'))
答案 1 :(得分:0)
可能有一个有多个连接和聚合的工作解决方案,但我想到非规范化:只需将cur_status
字段添加到Project
并用信号更新它。