【问题标题】:Filtering projects by current status type when status is a ManyToManyField当状态为 ManyToManyField 时按当前状态类型过滤项目
【发布时间】:2011-10-25 15:09:43
【问题描述】:

有关背景,请参阅这个 SO 问题: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 属性,这只会为您提供最近收到此状态的项目,而不是当前具有此状态的所有项目。

【问题讨论】:

  • 为什么不能直接使用 ProjectStatusType 模型?
  • 你可以,但这并不能真正解决问题。查看有问题的更新。

标签: django


【解决方案1】:

基本上问题是如何通过比较查询集的两个字段来过滤查询集: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'))

【讨论】:

  • 把它钉在头上。我完全忘记了F。现在的问题似乎很愚蠢,但谢谢。
【解决方案2】:

可能存在具有多个连接和聚合的有效解决方案,但我会考虑非规范化:只需将 cur_status 字段添加到 Project 并使用信号更新它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 2011-03-18
    • 2021-02-02
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    相关资源
    最近更新 更多