0

这是关于一个应用程序,它启用了一些协作审核功能,有点类似于 Stackoverflow。

当前状态

我有一个这样的 Django ORM 查询:

versions = Version.objects.filter(is_reviewed=False).exclude(moderations__user__pk=request.user.id).order_by('content_type__id', 'object_id', '-number').distinct('content_type', 'object_id')

每个内容对象可以具有由用户创建的任意数量的版本。我在这里所做的是获取来自其他用户的所有未审核版本,但每个内容对象仅获取最新版本。

问题

但我想添加另一个排除条件:如果内容对象具有较新版本,is_reviewed=True则不应返回以前的版本。不过,未审查的较新的应退回。知道怎么做吗?

一些例子。我假设这里的所有版本都是针对同一个内容对象的。

示例 A

  1. “第一版” - 未审查
  2. “改进版” - 未审查
  3. “更完善的版本” - 未审查

这应该返回第三行。按预期工作。

示例 B

  1. “第一版” -审查
  2. “改进版” - 未审查
  3. “更完善的版本” - 未审查

这应该返回第三行。按预期工作。

示例 C

  1. “第一版” - 未审查
  2. “改进版” -审查
  3. “更完善的版本” - 未审查

这应该返回第三行。按预期工作。

示例 D

  1. “第一版” - 未审查
  2. “改进版” - 未审查
  3. “更完善的版本” -评论

这应该不返回任何行。目前这不起作用。它将返回第二行,这不是它打算做的。

/编辑

这是我的模型:http ://sql.nopaste.dk/p48981

4

1 回答 1

1

我喜欢编写查询集方法来帮助解释我们正在尝试做的事情,并从那里向后工作。

Version.objects.newest_by_content_type().unreviewed()

然后,我们只需要查询集/管理器方法。[注意:我正在使用构建更高级别的查询 API中描述的模式将这些方法添加到查询集]。

事实证明,这是您已经编写的代码,只是顺序略有不同。

def newest_by_content_type(self):
    return self.order_by('content_type__id', 'object_id', '-updated').distinct('content_type', 'object_id')

def unreviewed(self):
    return self.filter(is_reviewed=False)

然后,您可以使用此查询集执行其他操作。例如,删除当前用户拥有的那些。

这个答案的前一个化身讨论了一个替代解决方案,使用 asuperseded_bysupersedes自我关系:

class Version(models.Model):
    supersedes = models.ForeignKey('Version', 
        related_name='superseded_by', null=True, blank=True)

然后,您可以通过以下方式获取所有未取代的对象:

Version.objects.filter(superseded_by=None)

根据约束条件,将 aOneToOneField用于取代关系可能是有意义的:如果一个版本最多只能被一个版本取代,并且一个版本只能取代一个版本。例如,也可以将它与 HTTP 标头一起使用,并在412 Precondition Failed尝试再次取代已经被取代的对象时返回。这在版本链是“直的”并且不允许分支的情况下是有意义的。

于 2013-06-20T07:25:47.133 回答