【问题标题】:Django ORM: filter primary model based on chronological fields from related modelDjango ORM:根据相关模型中的时间字段过滤主要模型
【发布时间】:2015-10-08 13:17:57
【问题描述】:

假设我们有以下模型:

class Patient(models.Model)
    name = models.CharField()
    # other fields following

class MedicalFile(model.Model)
    patient = models.ForeignKey(Patient, related_name='files')
    date = models.DateField()
    diagnostic = models.CharField()

我们希望为患者构建一个视图集,我们希望在其中根据他们最后可用/有效的诊断过滤患者记录。

如果不使用原始 SQL,我不知道如何解决这个问题。是否有一种仅使用 Django 查询集语法来构建此语句的最佳方法?


我是如何解决这个问题的?

我确定这不太好,但它最适合过滤大型数据集。

这个想法是使用在数据库层实现的视图,我们将在其中查询所有患者及其相关的最新医疗文件,而不是将 Django 实体映射到该视图。当然,我们会将新模型设为非托管。

为什么要走这么远的路?因为在新模型上,我们可以使用“可重用”的 Django 查询语法。当然,来自数据库的视图不可重用,必须为每个 db 后端解决方案重新创建。

考虑到 Postgres,这将是视图定义:

SELECT
    p.*,
    f.*
FROM Person p
    LEFT JOIN (
        SELECT
            *,
            max(date) OVER (PARTITION BY person_id) AS latest_date
        FROM MedicalFile
    ) AS mf ON mf.person_id = p.person_id
WHERE
    mf.latest_date IS NULL OR mf.latest_date = mf.date

然后我们可以像这样创建关联模型

class LatestMedicalFile(models.Model):
    patient = models.OneToOneField(Patient, related_name="latest_file")
    date = models.DateField()
    diagnostic = models.CharField()

    class Meta:
        managed = False
        db_table = '<your view name here>'

最后,我们的查询可以这样写:

Patient.objects.filter(latest_file__diagnostic='flu')

在我看来,这既不直观,也不干净。有什么想法吗?

【问题讨论】:

  • 所以基本上,在文件中按日期排序?
  • ...是的,按 Patient.id 进行分区。有一个挑战(对我来说)要获得一个表示,在同一记录(查询行)中,我从最新的可用患者文件中获取患者数据和数据(在这种情况下是诊断数据)。
  • 你可以展示你期望的SQLite吗?它应该可以转换quesryset styntax。
  • 我知道如何用 2 个查询来做到这一点,以前用过那种模式,你从来都不喜欢它....
  • 可以展示一下你的sql语法吗?

标签: python django


【解决方案1】:

如果您有兴趣查看文件:

MedicalFile.objects.annotate(
    maxdate=Max(
        'patient__files__date'
        )).filter(
            maxdate=F('date'),
            diagnosis="flu").select_related(
                'patient'
            )

如果你想要病人:

Patient.objects.annotate(
    maxdate=Max(
        'files__date'
        )).filter(
            maxdate=F('files__date'),
            files__diagnosis="flu"))

非常感谢Roba,协作提问/回答是我最喜欢的 SO 用户类型。

【讨论】:

  • 不够:如果患者有他的最新文件
  • 我彻底误解了这个查询。您更新的问题需要我考虑一下,但我确信我可以想出一些自然而不会导致原始的东西。
  • 任何帮助我解决这个问题的人都非常感激......谢谢伙计。
  • 您能帮我确认一下这是否符合您的要求吗?这是一个整洁的模式。
  • 我已经跟进了你的技术。即使您使用主表,它也能正常工作,因为正在引入一个额外的连接以及有子句: Patient.objects.annotate(latest_date=Max('files__date')).filter(latest_date=F( '文件__日期'),文件__诊断='流感')。请更新您的答案,以便我将其标记为正确。
猜你喜欢
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 2017-06-22
  • 1970-01-01
相关资源
最近更新 更多