如何将存储过程移到Django模型类并在过滤/排除中使用?

0 投票
2 回答
930 浏览
提问于 2025-04-16 15:12

如何将存储过程移到Django模型类中,并在过滤或排除时使用它们?正如这里所说的在Django的ORM中访问存储过程的最佳方法,这是可能的。

换句话说,我该如何实现类似这样的操作:

class Project(models.Model):
    name = models.CharField()
    def is_finished(self):
        count = self.task_set.all().count()
        count2 = self.task_set.filter(finished=True).count()
        if count == count2:
            return True
        else:
            return False

class Task(models.Model):
    name = models.CharField()
    finished = models.BooleanField()
    project = models.ForeignKey(Project)

#somewhere else in the code...
finished_projects = Project.objects.filter(is_finished=True)

2 个回答

0
  1. 一种解决方案是反规范化:

    class Project(models.Model):
        name = models.CharField()
        is_finished = models.BooleanField()
    
        def _is_finished(self):    
            return self.task_set.exclude(finished=True).exists()
    
        def update_finished(self):
            self.is_finished = self._is_finished()
            self.save() 
    
    class Task(models.Model):
        name = models.CharField()
        finished = models.BooleanField()
        project = models.ForeignKey(Project)
    
        def save(*args, **kwargs):
            res = super(Task, self).save(*args, **kwargs)
            self.project.update_finished()
            return res
    
    #somewhere else in the code...
    finished_projects = Project.objects.filter(is_finished=True)
    

    如果你的读取操作远远多于写入操作,那这样做是很不错的,因为读取会非常快(比使用存储过程还快)。不过,你需要自己注意数据的一致性。

  2. Django的聚合功能或者“原始”支持通常可以用来实现存储过程的逻辑。

1

我不太明白你为什么在这个情况下提到存储过程。

不过如果我理解你的例子没错,你的问题是你只能通过数据库表中有对应字段的模型字段来进行过滤。

所以你不能使用Django的ORM来通过方法和属性进行过滤。

但是你可以通过列表推导式来实现你想要的效果:

finished_projects = [p for p in Project.objects.all() if p.is_finished()]

撰写回答