返回当前项目状态(即关于Django ManyToMany关系的最近日期)

时间:2011-10-25 13:35:21

标签: django database-design django-models database-schema

架构描述

项目的状态可能会随时间而变化。为了跟踪一段时间内的状态,我通过Project中间表在ProjectStatusType模型和ProjectStatus模型之间创建了多对多关系。

虽然这允许跟踪项目的状态,但它增加了模式的复杂性,因此检索项目的当前状态或检索所有打开的项目更加困难。

enter image description here

用例

我希望能够返回所有处于给定状态的项目,例如所有open个项目。例如,当用户转到http://www.example.com/projects时,我希望默认情况下只有open项目显示在表格中。

问题

  1. 我应该对模式进行非规范化并在current_status模型中添加Project字段吗?
  2. 如果我不应该反规范化,我应该使用什么策略来检索每个项目的当前状态?我应该在Project模型上创建一个检索当前状态的属性吗?

2 个答案:

答案 0 :(得分:1)

如果您不需要搜索它,我会在Project模型上创建一个属性。您可以使用Max功能aggregate来获取最新日期的记录。

from django.db.models import Max

class Project(models.Model):
    [...]

    @property
    def status_date(self):
        return self.projectstatus_set.aggregate(newest=Max('status_date'))['newest']

此战略记录在案here

如果您需要进行查找,则应对其进行非规范化并向Project添加字段。您可以使用信号使其保持最新状态。您可能希望在post_save字段中添加ProjectStatus侦听器,这会将其项目的日期设置为状态'。

from django.db.signals import post_save

def update_status_date(sender, instance=None, **kwargs):
    project = instance.project
    project.status_date = max(project.status_date, instance.status_date)
    project.save()
post_save.connect(update_status_date, sender=ProjectStatus)

您可以阅读有关信号here的更多信息。

==

编辑:自从写完我原来的答案后,OP已经稍微澄清了他的问题,他的澄清改变了我的两个策略的示例代码,尽管不是他们的基本结构。对于那些可能需要更多类似于我认为我当时正在回答的问题的人,我想留下原始答案。

在我的第一个例子中,他并不真正想要最新的status_date本身,而是最新的项目状态类型。这将大大改变财产;您根本不需要使用MAX() SQL构造;你只想要按日期降序排序时附加到这个对象的第一条记录:

class Project(models.Model):
    [...]

    @property
    def project_status(self):
        return self.status.order_by('-status_date')[0]

围绕这个的用例仍然是相同的。如果你总是首先得到一个项目,然后想知道它的当前状态,这是正确的方法。如果您需要按状态索引项目,则需要进行非规范化。这仍然是通过信号完成的,但不是像我上面的示例中那样保存日期,您可能想要保存描述。但原则仍然是相同的。

答案 1 :(得分:0)

根据您的描述,我假设您实际上使用ProjectStatus作为through的{​​{1}},并且您已经存储了关于此关系的额外数据那个模特。如果其中一项额外数据尚未设置该特定状态的日期时间,我会将其添加到您的模型中。

然后,您可以按日期时间降序ManyToManyField,降序,这样返回的第一个ProjectStatus将始终是最新的(当前)。