Python 使用Django为多个反向外键选择相关和预取相关?

Python 使用Django为多个反向外键选择相关和预取相关?,python,django,django-models,Python,Django,Django Models,我当前在访问queryset中的值时遇到问题。我的应用程序有一个models.py,设置如下: class Company(models.Model): name = models.Charfield(max_length=250) class Patient(models.Model): status_choices = [ ('A', 'Current Admission'), ('D', 'Discharged'),

我当前在访问queryset中的值时遇到问题。我的应用程序有一个models.py,设置如下:

class Company(models.Model):
    name = models.Charfield(max_length=250)

class Patient(models.Model):

        status_choices = [
        ('A', 'Current Admission'),
        ('D', 'Discharged'),
        ('U', 'Unknown'),
    ]

    first_name = models.CharField(max_length=250)
    last_name = models.CharField(max_length=250)
    patient_status = models.CharField(
        max_length=15,
        choices=status_choices,
        null=True, default='U',
        verbose_name='Patient Status'
    )
    related_company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='patients')

class PatientStay(models.Model):
    admit_date = models.DateField()
    projected_dc_date = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)
    stay_to_patient_relationship = models.ForeignKey(Patient, on_delete=models.CASCADE, related_name='stays')
    
class PatientLOC(models.Model):
    loc_to_stay_relation = models.ForeignKey(PatientStay, on_delete=models.CASCADE, related_name='locs')
    level_of_care = models.CharField(max_length=30)
    loc_start = models.DateField(null=True)
    loc_end = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)

company = Company.objects.select_related().prefetch_related('patients__stays', 'patients__stays__locs').get(id=2)

patients = company.patients.all()

for patient in patients:
    ...:     print(patient)
    ...:     print(patient.stays.all())
我试图做的是查询(对于特定公司)患者、他们的相关住院时间(仅针对活跃期进行筛选)以及他们的相关PatientLOC

这样的结果:

class Company(models.Model):
    name = models.Charfield(max_length=250)

class Patient(models.Model):

        status_choices = [
        ('A', 'Current Admission'),
        ('D', 'Discharged'),
        ('U', 'Unknown'),
    ]

    first_name = models.CharField(max_length=250)
    last_name = models.CharField(max_length=250)
    patient_status = models.CharField(
        max_length=15,
        choices=status_choices,
        null=True, default='U',
        verbose_name='Patient Status'
    )
    related_company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='patients')

class PatientStay(models.Model):
    admit_date = models.DateField()
    projected_dc_date = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)
    stay_to_patient_relationship = models.ForeignKey(Patient, on_delete=models.CASCADE, related_name='stays')
    
class PatientLOC(models.Model):
    loc_to_stay_relation = models.ForeignKey(PatientStay, on_delete=models.CASCADE, related_name='locs')
    level_of_care = models.CharField(max_length=30)
    loc_start = models.DateField(null=True)
    loc_end = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)

company = Company.objects.select_related().prefetch_related('patients__stays', 'patients__stays__locs').get(id=2)

patients = company.patients.all()

for patient in patients:
    ...:     print(patient)
    ...:     print(patient.stays.all())
  • 公司:
  • -病人
  • --停留
  • ---LOC's
  • -病人
  • --停留
  • ---LOC's
  • -病人
  • --停留
  • ---LOC's
我提出了以下建议(过滤除外):

我可以通过这个循环找到病人和住院病人,但我似乎无法找到那些病人的LOC。所以,我可以这样做:

class Company(models.Model):
    name = models.Charfield(max_length=250)

class Patient(models.Model):

        status_choices = [
        ('A', 'Current Admission'),
        ('D', 'Discharged'),
        ('U', 'Unknown'),
    ]

    first_name = models.CharField(max_length=250)
    last_name = models.CharField(max_length=250)
    patient_status = models.CharField(
        max_length=15,
        choices=status_choices,
        null=True, default='U',
        verbose_name='Patient Status'
    )
    related_company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='patients')

class PatientStay(models.Model):
    admit_date = models.DateField()
    projected_dc_date = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)
    stay_to_patient_relationship = models.ForeignKey(Patient, on_delete=models.CASCADE, related_name='stays')
    
class PatientLOC(models.Model):
    loc_to_stay_relation = models.ForeignKey(PatientStay, on_delete=models.CASCADE, related_name='locs')
    level_of_care = models.CharField(max_length=30)
    loc_start = models.DateField(null=True)
    loc_end = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=False)

company = Company.objects.select_related().prefetch_related('patients__stays', 'patients__stays__locs').get(id=2)

patients = company.patients.all()

for patient in patients:
    ...:     print(patient)
    ...:     print(patient.stays.all())
但这样的事情是行不通的:

company = Company.objects.select_related().prefetch_related('patients__stays', 'patients__stays__locs').get(id=2)
patients = company.patients.all()

for patient in patients:
     ...:     print(patient)
     ...:     for stay in patient.stays.all():
     ...:         print(stay)
     ...:         for loc in patient.stays.locs.all():
     ...:             print(loc)

除了我使用一堆嵌套for循环之外,最好的方法是什么?在psuedocode中,有没有一种方法可以像这样对患者进行循环:

for patient in patients:
    print(patient)
    print(patient.stay)
    print(patient.stay.loc)
我已经为此挣扎了一段时间,我已经猜不出来了。文档让我找到了与select_相关的和prefetch_相关的(我确信我在某种程度上使用了错误的方法)


感谢您的帮助。

您可以嵌套预回迁电话:

from django.db.models import Prefetch
patients = Patient.objects.filter(company__id=2).prefetch_related(
   Prefetch(
      'stays',
      queryset=PatientStay.objects.prefetch_related('locs')
   ))

for patient in patients:
   print(patient)
   print([stay for stay in patient.stays.all()])
   print([loc for stay in patient.stays.all() for loc in stay.locs.all()])

仅供参考:
select\u related
在这里没有为您做任何事情。与预取相关的操作只会保存数据库行程。如果您不关心查询,那么嵌套for循环代码的唯一问题是patient.stays.locs.all()的行
-这将是loc in staid.locs.all()的
-您就快到了!这非常有用,感谢您提供嵌套的预回迁呼叫信息。如何从模板访问此文件?我不能(至少我可以看到)在模板中使用列表理解,也不会像stay-in-patient.stay.filter(is_-active=True)那样使用任何内容。我是否需要以某种方式在我的视图函数中执行这些操作,然后以这种方式保存它们>作为上下文传递?我正在为这一个而奋斗。没关系,我能够循环通过它,但我必须在没有理解的情况下使用Django过滤器,而不是queryset过滤器。