Django 覆盖 filter() 而不更改现有代码逻辑

Posted

技术标签:

【中文标题】Django 覆盖 filter() 而不更改现有代码逻辑【英文标题】:Django overriding filter() without change existing code logic 【发布时间】:2022-01-18 05:06:14 【问题描述】:

我有一个生产中的表,它集成在系统中的任何地方,现在我需要在表中添加一个具有默认值的新列,但不想更改所有现有逻辑,最好的方法是什么这样做?

class People(models.Model):
      name = models.CharField(max_length=20)
      gender = models.CharField(max_length=20)
      class = models.CharField(max_length=20)

在系统中,我们到处都有这种查询

People.objects.filter(gender='male')

People.objects.filter(gender='female', class="3rd")
...

现在我们需要添加一个新字段:

class People(models.Model):
      name = models.CharField(max_length=20)
      gender = models.CharField(max_length=20)
      class = models.CharField(max_length=20)
      graduated = models.BooleanField(default=False)

假设所有现有数据应该有graduated 是False,所以如果我们可以在每个查询上添加graduated=False,那么所有现有逻辑都应该工作,但是有什么方法可以做到我们不需要更改任何现有代码,但他们会假定 graduated=False?

【问题讨论】:

【参考方案1】:

是的,你可以让.objects 只保留Peoplegraduated=False 的经理:

class PeopleManager(models.Manager):
    
    def get_queryset(self):
        return super().get_queryset().filter(graduated=False)

class People(models.Model):
    name = models.CharField(max_length=20)
    gender = models.CharField(max_length=20)
    class = models.CharField(max_length=20)
    graduated = models.BooleanField(default=False)
    
    objects = PeopleManager()
    all = models.Manager()

您可以使用People.all.all() 检索所有People,使用People.objects.all() 检索所有未毕业的People

话虽如此,我不建议这样做:People.objects.all() 通常给人的印象是人们会检索所有 People。正如Python 之禅所说:“显式优于隐式”:最好是代码解释和提示它正在做什么,而不是将过滤移动到隐藏在管理器中的某个地方。

【讨论】:

以上是关于Django 覆盖 filter() 而不更改现有代码逻辑的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PlistBuddy 添加设置而不覆盖现有设置?

将数据添加到现有 JSON 文件而不覆盖它

向 tar 文件添加条目而不覆盖其现有内容

在 Fortran 中写入现有文件而不覆盖

如何通过本机反应将新字段数据更新到现有文档而不覆盖firebase-9中的现有数据

如何使用 NSUserDefaults 注册用户默认值而不覆盖现有值?