Django Queryset:按相关项目管理器过滤

Django Queryset: filtering by related item manager

我有包含多个内容块的页面模型。

class Page(models.Model):
    ...

class Block(models.Model):
    page = models.ForeignKey(Page)
    ...

Block 有一些其他属性决定它是否被认为是 "active" (一对布尔值和一个日期时间字段)。我有一个 Block 模型的管理器,这样我就可以获得活动块列表

Block.objects.active()
Page.objects.first().block_set.active()

我希望能够将查询集写入 return 只有 Page 个具有活动块的对象。我想使用现有的 Block 活动管理器来执行此操作,因此我只定义一次 "active" 块的内容(DRY)。 IE 类似于:

Page.objects.annotate(count=Count('block__active')).filter(count__gt=0)

显然这不起作用,因为 active 不是 Block 的 属性。有什么方法可以使用现有的 Block 管理器来实现这一点?

据我所知,没有办法使用单个 queryset 来实现它,因为您想使用您的经理中可用的 active()。但是您可以通过将 related name 添加到 Block 模型中的 Page 来实现结果:

class Block(models.Model):
    page = models.ForeignKey(Page, related_name='related_block')
    ...

现在您的代码应该是:

active_blocks = Block.objects.active()  # Queryset with all active blocks
# Queryset of Pages with Block in 'active_blocks' 
active_pages = Page.objects.filter(related_block__in=active_blocks)

现在在此 QuerySet 上,您可以执行 annonate 或任何您希望在 Page 的 QuerySet 上允许的操作。

为什么不直接在模型上添加一个布尔字段,例如 is_active,然后在 save()set_active() 上更新它?然后您就可以通过该字段查询您的模型。