Django ORM查询在两个字段上连接不相关的表

2024-07-01 07:13:22 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

我正在写一个程序,在这个程序中,我注册了在不同医疗场所对患者进行的治疗。每次治疗都是在特定的身体部位进行的,每个医疗场所都可以定义自己命名这些身体部位的方式

我的模型是这样的:

class Treatment(Model):
    medical_place = ForeignKey(to=MedicalPlace, on_delete=PROTECT, related_name='treatments')
    body_part = CharField(max_length=64, choices=BodyPart.choices(), db_index=True)
    ... (some other fields) ...

class LocalProcedure(ProcedureBase):
    medical_place = ForeignKey(to=MedicalPlace, on_delete=PROTECT, related_name='procedures')
    identifier = CharField(verbose_name=_('Procedure number'), max_length=64, blank=False, null=False)
    description = CharField(verbose_name=_('Procedure description'), max_length=256, blank=True, null=False)
    body_part = CharField(max_length=64, choices=BodyPart.choices(), blank=False, db_index=True)

    class Meta:
        unique_together = (('body_part', 'medical_place', 'identifier'),)

我需要检索带有注释的“LocalProcedure”对象列表:

  • 相关治疗计数
  • 完成的相关治疗计数 到X天前(治疗模型创建了datetime字段,我没有 此处显示)

到目前为止我已经尝试过的解决方案

我可以在使用子查询时检索带注释的LocalProcedures列表:

    related_treatments = Treatment.objects.filter(
        body_part=OuterRef('body_part'),
        medical_places=OuterRef('medical_place'),
    ).values(
        f'body_part',
    )
    LocalProcedure.objects.annotate(
        treatments_count = Subquery(related_treatments.annotate(count=Count('pk')).values('count'),
        treatments_count = Subquery(related_treatments.filter(created__gt=now()).annotate(count=Count('pk')).values('count'),
    )

但这个解决方案确实执行子查询,而连接这两个表(在编写原始查询时)要快得多

谢谢你的帮助

部分有效溶液(最后标记为已接受)

@ruddra在这里发布的答案确实很有帮助,但并不能完全满足我的需要。我知道我通过medical_place字段在LocalProcedure和Treatment对象之间建立了关系,但这意味着查询将有另一个完全不必要的join子句

对于正在寻找不使用ForeignKey将关系引入其模型的人来说,有一种称为ForeignObject的方法,可用于使用任何字段创建两个对象之间的关系


Tags: name模型falsecountplacebodylengthmax
1条回答
网友
1楼 · 发布于 2024-07-01 07:13:22

这可能要简单得多:

from django.db.models import Count, F, Q

LocalProcedure.objects.annotate(
    treatments_count=Count(
        'medical_places__treatments',
        filter=Q(body_part=F('body_part'))
    ),
    treatments_count_x=Count(
        'medical_places__treatments',
        filter=Q(body_part=F('body_part'))|Q(created_gt=now())
    )
)

这里我只是使用基于^{}的过滤器进行计数

相关问题 更多 >

    热门问题