给定以下模型(使用django-simple-history):

class MyModel (models.Model):
    status = models.IntegerField()
    history = HistoricalRecords()

我想获取在给定日期没有特定status的所有实例(即在限制日期具有不同状态的所有实例,加上当时不存在的所有实例).

以下查询将返回在限制日期之前任何时候从未有status = 4的所有实例:

MyModel.filter (~Exists (
    MyModel.history.filter (
        id = OuterRef ("id"),
        history_date__lte = limit_date,
        status = 4))

但不幸的是,它还删除了在过go 某个日期有status = 4的实例,然后在限制日期更改为不同的status,我想保留这些实例.

以下内容应该给出正确的结果:

MyModel.filter (~Exists (
    MyModel.history.filter (
        id = OuterRef ("id"),
        history_date__lte = limit_date)
   .order_by ("-history_date")
   [:1]
   .filter (status = 4)))

不幸的是,它不起作用:Cannot filter a query once a slice has been taken.question链接到这documentation page,这解释了在查询集被切片后不允许过滤.

请注意,错误来自Django中的assert.如果我在django/db/models/query.py:953中注释掉assert,那么代码似乎有效并给出预期结果.然而,在upstream 依赖项中 comments 掉assert并不是生产中可行的解决方案.

那么,有没有一种干净的方法可以根据对象的过go 状态过滤我的查询集呢?

推荐答案

历史模型仅在物品changed时保存记录,而不是每天保存.因此,我们可以通过以下方式获得特定日期的状态:

from django.db.models import OuterRef, Q, Subquery

MyModel.annotate(
    historic_status=Subquery(
        MyModel.history.filter(id=OuterRef('id'), history_date__lte=limit_date)
        .order_by('-history_date')
        .values('status')[:1]
    )
).filter(~Q(history_status=4) | Q(history_status=None))

因此,我们首先寻找日期为before或等于limit_date的历史模型的status.通过首先使用最近的history_date来订购它,我们就可以获得最新的状态.

因此,如果当时记录不存在,则NULL(None),这将在102or时将historic_status设置为status.

因此,我们可以过滤具有history_status而不是4个的MyModel(并且我们显式添加了NULL判断),尽管通常以下内容应该足够:

from django.db.models import OuterRef, Q, Subquery

MyModel.annotate(
    historic_status=Subquery(
        MyModel.history.filter(id=OuterRef('id'), history_date__lte=limit_date)
        .order_by('-history_date')
        .values('status')[:1]
    )
).filter(~Q(history_status=4))

Python相关问答推荐

累积汇总两极列表[struct[]]

合并其中一个具有重叠范围的两个框架的最佳方法是什么?

自动编码器和极坐标

如何在Pygame中绘制右对齐的文本?

使用Python Great Expectations和python-oracledb

code _tkinter. Tcl错误:窗口路径名称错误.!按钮4"

在编写要Excel的数据透视框架时修复标题行

遵循轮廓中对象方向的计算线

使用Ubuntu、Python和Weasyprint的Docker文件-venv的问题

跟踪我已从数组中 Select 的样本的最有效方法

根据网格和相机参数渲染深度

当密钥是复合且唯一时,Pandas合并抱怨标签不唯一

由于NEP 50,向uint 8添加-256的代码是否会在numpy 2中失败?

如何让剧作家等待Python中出现特定cookie(然后返回它)?

如何根据参数推断对象的返回类型?

. str.替换pandas.series的方法未按预期工作

组/群集按字符串中的子字符串或子字符串中的字符串轮询数据框

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?

使用Python和文件进行模糊输出

如何在Python中使用Pandas将R s Tukey s HSD表转换为相关矩阵''