我正在研究患者数据库。两个相关的类,一个用于存储患者的详细信息,另一个用于跟踪不同类型患者的总数。跟踪器类如下:
class Case (models.Model):
id = models.AutoField(primary_key=True)
time_stamp = models.DateTimeField(null=True, auto_now_add=True)
is_dicom = models.BooleanField(null=False, blank=True)
PatientId = models.IntegerField(null=True, blank=True, db_column="patientid")
def __unicode__(self):
return "%s" % self.id
这有一个'PatientId'字段,它引用两个不同的类(因此不是任何一个类的外键),只是将引用类的pk存储为整数。引用类是Patient和PatientJpeg,它们在save()上运行类似的代码:
class Patient(models.Model):
id = models.AutoField(primary_key=True, db_column='pk')
case_id = models.OneToOneField(Case, null=True, blank=True, db_column='case_id')
pat_birthdate = models.CharField(max_length=160, blank=True)
pat_sex = models.CharField(max_length=160, blank=True)
created_time = models.DateTimeField(null=True, auto_now_add=True)
updated_time = models.DateTimeField(null=True, auto_now_add=True)
class Meta:
db_table = 'patient'
def __unicode__(self):
return u"%s" % self.id
def save(self):
if not(self.case_id):
x = 1
while (x < Case.objects.count() + 1):
if not Case.objects.filter(pk=x).exists():
break
else:
x += 1
newCase = Case(x)
newCase.is_dicom = True
newCase.PatientId = self.id
newCase.save()
self.case_id = newCase
super(Patient, self).save()
class PatientJpeg (models.Model):
id = models.AutoField(primary_key=True, db_column='pk')
case_id = models.OneToOneField(Case, null=True, blank=True, db_column='case_id')
pat_age = models.CharField(max_length=160, null=True, blank=True)
pat_sex = models.CharField(max_length=160, null=True, blank=True)
def __unicode__(self):
return u"%s" % self.id
def jpeg_paths(self):
array = []
for x in self.jpeg_set.all():
array.append(x.image.path)
return array
class Meta:
db_table = 'patient_jpeg'
def save(self):
if not(self.case_id):
x = 1
while (x < Case.objects.count() + 1):
if not Case.objects.filter(pk=x).exists():
break
else:
x += 1
newCase = Case(x)
newCase.is_dicom = False
newCase.PatientId = self.id
newCase.save()
self.case_id = newCase
super(PatientJpeg, self).save()
问题在于,当我保存Patient或PatientJpeg时,PatientId字段(Case类中的整数字段)保持为空。我已经在shell中复制了这段代码并且行为正常,我不知道为什么它在django中没有表现。
感谢您查看代码
答案 0 :(得分:2)
这段代码是礼貌的,非常可怕。每次创建新病人时,它都会进行疯狂的数据库访问 - 假设您有1000个案例,只需保存一个新病人就会导致超过1000个数据库调用。
奇怪的是,我无法理解你为什么需要它。案例ID是一个任意数字,因此似乎没有任何特殊原因需要迭代现有的案例ID来查找空白案例ID。鉴于ID是AutoField,因此无论如何都将由数据库分配。只需摆脱所有这些,只需创建一个新案例。
另一个问题当然是第一次保存患者时不存在self.id.您需要确保在分配案例之前保存它。
def save(self, *args, **kwargs):
if not(self.case_id):
if not self.id:
super(Patient, self).save(*args, **kwargs)
newCase = Case()
newCase.is_dicom = True
newCase.PatientId = self.id
newCase.save()
self.case_id = newCase
super(Patient, self).save(*args, **kwargs)
其他指针:不要调用你的一对一关系case_id
:它是一个案例对象,而不是一个ID,所以只需称它为case
。此外,您应该创建一个抽象类作为Patient和PatientJpeg的父级,并将自定义保存逻辑放在那里。最后,您的jpeg_paths
方法可以替换为列表推导。
答案 1 :(得分:0)
您致电newCase.save()
的时间,您的PatientJpeg
记录尚未保存到数据库中。当您尝试将它们保存到数据库时,会评估django中的AutoField
,因为必须由数据库生成id
。因此,当您致电newCase.save()
时,self.id
中的newCase.PatientId = self.id
为None
您致电super(PatientJpeg, self).save()
后必须保存数据,因此self.id
的有效值不会为None
如果您的ForeignKey
可能会对多个表格感兴趣,我建议您使用ContentTypes Framework。
答案 2 :(得分:0)
在创建Case
之前,您需要保存Patient
,因此我认为save
方法应该是这样的:
def save(self):
if not self.id:
super(PatientJpeg, self).save()
if not self.case_id:
x = 1
while (x < Case.objects.count() + 1):
if not Case.objects.filter(pk=x).exists():
break
else:
x += 1
newCase = Case(x)
newCase.is_dicom = False
newCase.PatientId = self.id
newCase.save()
self.case_id = newCase
super(PatientJpeg, self).save()