【问题标题】:Filter objects in Django 2 if all objects in subquery have specific value如果子查询中的所有对象都具有特定值,则在 Django 2 中过滤对象
【发布时间】:2018-07-19 14:32:00
【问题描述】:

我有以下型号:

class FactoryDevice(models.Model)
    ...

class InspectionRegister(models.Model)
    factory_device = models.ForeignKey(FactoryDevice)
    inspection_date = models.DateTimeField()
    status = models.CharField(choices=choices.STATUS)

这是场景:

在工厂,每周都会检查设备。

我只想过滤FactoryDevices,最后五个相关InspectionRegisters 的状态为choices.REPPROVED。如果FactoryDevice 中最后五个InspectionRegister 之一的状态不是choices.REPPROVED,那么这个FactoryDevice 一定不能出现在结果中。

【问题讨论】:

  • 我假设状态是某种IntegerField?因为现在它根本不是数据库中的一列。
  • 没有五个InspectionRegisters 的设备应该怎么办?
  • 如果一个设备少于五个,则它不会出现在结果中
  • 修复模型中的状态

标签: python django filter subquery django-queryset


【解决方案1】:

首先,我会为你的反向关系定义一个related_name,让你的生活更轻松:

factory_device = models.ForeignKey(FactoryDevice, related_name='inspections')

那么这样的事情可能会起作用:

queryset = FactoryDevice.objects
.prefetch_related(Prefetch(
    'inspections', # your related name
    InspectionRegister.objects.order_by('-inspection_date')[:5].filter(status=choices.REPPROVED),
    to_attr='failed_inspections'
)
.annotate(failed_count=Count('failed_inspections'))
)
.filter(failed_count__gte=5)

【讨论】:

  • 只计算状态等于choices.REPPROVEDInspectionRegisters 可能是这样的吗? ... Count(Case(When(late_five_inspections__status=choices.REPPROVED, then=1), output_field=CharField())) ...
  • 对该查询的上下文有点困惑。我会这样做:`FactoryDe​​vice.objects.filter(inspections__status=choices.REPPROVED).annotate(num_failed_inspections=Count('inspections'))`
  • 它必须被视为连续值。如果最后五个连续值是 'choices.REPPROVED'
  • 这就是我第一次做order_by('-inspection_date')[:5]的原因。我基本上是按日期顺序对检查进行排序,然后取最近的 5 个。然后我们看看这 5 个最近的检查是否都是失败状态。
  • 现在(When(failed_inspections__status=choices.REPPROVED, then=1) 出现错误。在docs 中:“使用 to_attr 时,预取的结果存储在列表中”,因此,failed_inspections 没有__status。如果我使用相关的inspections,它不遵循order_by 和限制`[:5]。它获取所有相关对象。
猜你喜欢
  • 1970-01-01
  • 2021-11-04
  • 2018-05-10
  • 2021-04-11
  • 1970-01-01
  • 2020-08-28
  • 2019-02-09
  • 2014-02-11
  • 1970-01-01
相关资源
最近更新 更多