Django save()方法没有产生所需的输出

时间:2014-02-01 10:04:33

标签: django django-models

我正在研究患者数据库。两个相关的类,一个用于存储患者的详细信息,另一个用于跟踪不同类型患者的总数。跟踪器类如下:

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中没有表现。

感谢您查看代码

3 个答案:

答案 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.idNone

您致电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()

同时查看django post_save signal