【问题标题】:Django ORM and chained select_relatedDjango ORM 和链式 select_related
【发布时间】:2020-03-21 07:39:03
【问题描述】:

如何使用 Django ORM 进行此查询?

这是一个多重连接,从一个表链接到另一个表。

有关 select 相关 (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#select-related) 的 Django 文档给出了一个示例,其中三个表通过外键“链接”:书籍 -> 作者 -> 城市。

b = Book.objects.select_related('author__hometown').get(id=4)

p = b.author # 不命中数据库。

c = p.hometown # 不命中数据库。

要“不命中数据库”必然意味着select查询连接了三个表。 因此查询生成的sql应该显示(我还没有检查)。

我的模型基于对现有数据库的分析,具有明确定义的外键。 我将提取以下模型。

SELECT *
     FROM  SERVICE 
     INNER JOIN VISIT ON SERVICE.VisitRecordID = VISIT.VisitRecordID 
     INNER JOIN  CMPATIENT ON VISIT.PatientNo = CM_PATIENT.PATIENT_ID

我可以使用的第一个连接

q = Service.objects.select_related('visitrecordid',).all()

这使得 sql 像:

SELECT * FROM [SERVICE] LEFT OUTER JOIN [VISIT] ON ([SERVICE].[VisitRecordID] = [VISIT].[VisitRecordID])

所以我得到的是左外连接,而不是内连接,这是一个问题。 但最重要的是,我不知道为什么 CmPatient 没有参与查询。

模型(摘录)

class Service(models.Model):
    servrecid = models.AutoField(db_column='ServRecID', primary_key=True)  # Field name made lowercase.
    visitrecordid = models.ForeignKey('Visit', models.DO_NOTHING, db_column='VisitRecordID', blank=True,
                                      null=True)  # Field name made lowercase.
    itemno = models.CharField(db_column='ItemNo', max_length=10, blank=True, null=True)  # Field name made lowercase.


class Visit(models.Model):
    visitrecordid = models.AutoField(db_column='VisitRecordID', primary_key=True)  # Field name made lowercase.
    patientno = models.ForeignKey(CmPatient, models.DO_NOTHING, db_column='PatientNo', blank=True,
                                  null=True)  # Field name made lowercase.
    visitdate = models.DateTimeField(db_column='VisitDate', blank=True, null=True)  # Field name made lowercase.
    servdoctor = models.CharField(db_column='ServDoctor', max_length=6, blank=True,
                                  null=True)  # Field name made lowercase.


class CmPatient(models.Model):
    patient_id = models.AutoField(db_column='PATIENT_ID', primary_key=True)  # Field name made lowercase.
    ur_no = models.CharField(db_column='UR_NO', max_length=9, blank=True, null=True)  # Field name made lowercase.
    external_id = models.CharField(db_column='EXTERNAL_ID', max_length=9, blank=True,
                                   null=True)  # Field name made lowercase.
    payer = models.ForeignKey('self', models.DO_NOTHING, db_column='PAYER_ID', blank=True,
                              null=True)  # Field name made lowercase.

【问题讨论】:

  • 你能分享你的 django 模型和你试图在这个查询中提取的数据(即列)吗?

标签: django django-models django-orm


【解决方案1】:

您可以通过__(两个下划线)遍历关系。所以你想要的是:

Service.objects.select_related('visitrecordid__patientno')

【讨论】:

  • 谢谢,我现在意识到我不知道如何阅读文档。
  • 附带问题,您是否与现有数据库集成?您的模型未定义,因为我希望找到定义的“正常”django 模型。特别是 _id 作为 ids,db_column 的使用并将外键定义为 patientno 和 visitrecordid(我建议分别为患者或 cm_patient 和 visit)。
  • 没错,模型是通过在大型数据库上运行 manage.py inspectdb 创建的。它也做得很好。
  • 啊,好吧。然后忽略我的建议。好吧。我仍然可能会重命名关系字段,以便在 ORM 方面更有意义。
  • 在这些情况下使用prefetch_related
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-25
  • 2010-12-09
  • 2019-02-23
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
相关资源
最近更新 更多