django 保存()导致在尝试更新现有记录时创建新记录

pnwntuvh  于 12个月前  发布在  Go
关注(0)|答案(1)|浏览(110)

所以我有以下模型:

class Session(models.Model):
    sessionid = models.CharField(max_length=10, primary_key=True)
    forgepass = models.ForeignKey(ForgeProfile, on_delete=models.CASCADE)
    programid = models.ForeignKey(TrainingProgram, on_delete=models.PROTECT)
    program_day = models.IntegerField()
    hours = models.IntegerField()
    session_date = models.DateField(default=timezone.now())
    verified = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        session_count = Session.objects.all().count()

        self.sessionid = 'S' + self.forgepass.forgepass + id_gen(session_count)

        super().save(*args, **kwargs)
    

    def __str__(self):
        return '{} - {}'.format(self.sessionid, self.session_date)

字符串
当在后端更新现有记录时,将使用新的sessionid和更新的值创建一条新记录,同时保留旧记录。

r6vfmomb

r6vfmomb1#

这是因为你每次都会生成一个新的主键,而主键是Django决定是否创建或更新的方式。
因此,只有在没有生成主键的情况下,才应该分配一个新的id,比如:

class Session(models.Model):
    sessionid = models.CharField(max_length=10, primary_key=True)
    forgepass = models.ForeignKey(ForgeProfile, on_delete=models.CASCADE)
    programid = models.ForeignKey(TrainingProgram, on_delete=models.PROTECT)
    program_day = models.IntegerField()
    hours = models.IntegerField()
    session_date = models.DateField(default=timezone.now())
    verified = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if not self.sessionid:
            session_count = Session.objects.all().count()
            self.sessionid = (
                'S' + self.forgepass.forgepass + id_gen(session_count)
            )
        return super().save(*args, **kwargs)

    def __str__(self):
        return '{} - {}'.format(self.sessionid, self.session_date)

字符串
这本身就有一个问题:如果self.forgepass.forgepass以某种方式发生了变化,它不会改变主键。
但事实上以任何形式格式化主键都不是一个好主意。你应该把主键看作是黑盒对象:可能是strint,但这是一个技术细节:不格式化它们。
如果你想给它分配一个sessionid,你可以添加一个(唯一的)额外的字段,但是不要使用主键。
另一个问题是,在这里保存一个对象至少需要三个查询:一个是获取项目的数量,一个是获取self.forgepass.forgepass,最后保存对象。如果你使用**.bulk_create(…)[Django-doc]进行批量创建,这就更成问题了,因为.save(…)**[Django-doc]被绕过了,所以请不要在.save()处理程序中添加逻辑。

相关问题