当状态为 ManyToManyField 时,按当前状态类型过滤项目
有关背景信息,请参阅此问题: 返回当前项目状态(即 Django ManyToMany 关系的最新日期)
当我思考这个问题时,它引发了我自己的一个问题。本质上,您的内容大致类似于以下内容:
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
属性,也只会为您提供最近收到此状态的项目,而不是当前具有此状态的所有项目。
For background see this SO question: Returning the current project status (i.e., most recent date on Django ManyToMany relationship)
As I was thinking about the problem, it sparked a question of my own. Essentially, you have something roughly similar to the following:
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)
To get the current status type for a particular project, you could do something like:
Project.status.order_by('-projectstatustype__created')[0]
But what if you wanted to get all projects whose current status is 'foo'?
Project.objects.filter(status__name='foo')
That would return projects who ever had a status of 'foo', whether or not it was the current status. You almost want to do something like (note the use of current
in the filter):
Project.objects.annotate(current=Max('projectstatustype__created')).filter(status__name='foo', projectstatustype__created=current)
Obviously, that won't work because in that context, current
is expected to be a Python variable within the current scope, but it got me wondering: is there some way to pass the same concept on though to the SQL, such that it will look for created dates that match the annotation that was just created?
UPDATE:
It was suggested by @akonsu to simply use the ProjectStatusType
model, instead. However that doesn't really solve anything.
ProjectStatusType.objects.filter(statustype__name='foo')
Returns all ProjectStatusType
with a status of 'foo'. You could then loop over the queryset and get each Project
with the project
attribute, but again, these will be projects that at some point in time had this status, not necessarily projects that have this status currently. Even if you tried something like:
ProjectStatusType.objects.filter(statustype__name='foo').order_by('-created')[0]
And then accessed the project
attribute, that would merely give you the project that most recently received this status, not all projects that currently have the status.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本上问题是如何通过比较查询集的两个字段来过滤查询集: https://docs.djangoproject.com/en/dev/topics/db/queries/#filters-can-reference-fields-on-the-model。
因此可以修复使用注释的原始查询:
<代码>
basically the question is how to filter a query set by comparing two of its fields: https://docs.djangoproject.com/en/dev/topics/db/queries/#filters-can-reference-fields-on-the-model.
so your original query that uses annotations can be fixed:
可能有一个具有多个连接和聚合的工作解决方案,但我会考虑非规范化:只需将
cur_status
字段添加到Project
并用信号更新它。May be there is a working solution with multiple joins and aggregation, but I'd think about denormalization: just add
cur_status
field toProject
and update it with signals.