首页 > 解决方案 > Django 从所有查询中排除字段

问题描述

我在 Heroku 上运行具有零停机时间功能的 Django。这意味着在部署期间,同一数据库上运行了两个版本的代码(旧的和新的)。这就是为什么我们需要避免任何向后不兼容的迁移。

是否有可能从给定模型的 Django 查询中排除字段?

假设我们有一个模型(版本 1):

class Person(models.Model):
    name = models.CharField()
    address = models.TextField()

在将来的某个时间,我们希望将地址移动到单独的表中。我们知道我们不应该删除一个字段以使旧代码正常工作,因此 Person 模型可能看起来像(版本 2):

class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey(Address)
    _address = models.TextField(db_name='address')

这样,如果旧代码将查询地址,即使数据库已迁移,它也会从 Person 表中获取地址(这将是一个旧值,但假设这不是一个大问题)。

现在我如何安全地删除_address字段?如果我们将部署版本 3 并_address删除字段,那么版本 2 的代码仍将尝试_address在选择时获取,即使它没有在任何地方使用并且会因“没有此类列”异常而失败。

有没有办法防止这种情况并在版本 2 的代码中将某些字段标记为“不可获取”?所以版本 2 不会删除字段,但不会再获取它,版本 3 将删除字段。

标签: pythondjangodatabase-migrationdjango-ormdjango-migrations

解决方案


defer您可以为所有查询集的特定字段/字段使用自定义对象管理器。

class CustomManager(models.Manager):
    def get_queryset(self):
        return super(CustomManager, self).get_queryset().defer('_address',)
class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey(Address)
    _address = models.TextField(db_name='address')

    objects = CustomManager()

之后,在您针对Person模型的任何查询集中,默认情况下都不会_address在查询中包含字段。


推荐阅读