Django ORM 和链接 select_related

Django ORM and chained select_related

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

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

有关 select 相关 (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#select-related) 的 Django 文档给出了一个示例,其中三个 table 通过外键 "chained":Book -> Author -> City .

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

p = b.author # Doesn't hit the database.

c = p.hometown # Doesn't hit the database.

到 "not hit the database" 必须意味着 select 查询连接三个 table。 因此查询生成的 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.

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

Service.objects.select_related('visitrecordid__patientno')