Django 从所有查询中排除字段
Django exclude field from all queries
我是 运行 Heroku 上的 Django,具有零停机时间功能。这意味着在部署期间,同一数据库上有两个版本的代码 运行(旧的和新的)。这就是为什么我们需要避免任何向后不兼容的迁移。
是否可以从给定模型的 Django 查询中排除字段?
假设我们有一个模型(版本 1):
class Person(models.Model):
name = models.CharField()
address = models.TextField()
在未来的某个时候,我们希望将地址移动到单独的 table。我们知道我们不应该删除旧代码的字段,因此 Person 模型可能看起来像(版本 2):
class Person(models.Model):
name = models.CharField()
address = models.ForeignKey(Address)
_address = models.TextField(db_name='address')
这样,如果旧代码将查询地址,即使数据库已迁移,它也会从 Person table 获取地址(这将是一个旧值,但假设这不是一个大问题)。
我现在如何安全地删除 _address
字段?如果我们将部署版本 3 并删除 _address
字段,那么版本 2 的代码仍将尝试在 select 上获取 _address
,即使它没有在任何地方使用并且会失败 "No such column" 例外。
有没有办法防止这种情况发生并在版本 2 的代码中将某些字段标记为 "non-fetchable"?所以版本 2 不会删除字段,但不会再获取它,版本 3 会删除字段。
是的,你可以做到:
QuerySet.defer():
"在一些复杂的数据建模情况下,您的模型可能包含很多字段,其中一些可能包含大量数据(例如,文本字段),或者需要昂贵的处理才能将它们转换为 Python 对象。如果您在某些情况下使用查询集的结果,而您在最初获取数据时不知道是否需要这些特定字段,则可以告诉 Django 不要从中检索它们数据库。 - docs
Entry.objects.defer("headline", "body")
或
从 django 1.8 开始:使用 values_list
. You can only include fields that you want. You can also use Queryset.only()
and Queryset.defer()
优化您的查询集查询。您也可以链接 defer()
调用
Entry.objects.values_list('id', 'headline')
您可以为 defer
您的所有查询集的特定 field/fields 使用自定义对象管理器。
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
字段。
我是 运行 Heroku 上的 Django,具有零停机时间功能。这意味着在部署期间,同一数据库上有两个版本的代码 运行(旧的和新的)。这就是为什么我们需要避免任何向后不兼容的迁移。
是否可以从给定模型的 Django 查询中排除字段?
假设我们有一个模型(版本 1):
class Person(models.Model):
name = models.CharField()
address = models.TextField()
在未来的某个时候,我们希望将地址移动到单独的 table。我们知道我们不应该删除旧代码的字段,因此 Person 模型可能看起来像(版本 2):
class Person(models.Model):
name = models.CharField()
address = models.ForeignKey(Address)
_address = models.TextField(db_name='address')
这样,如果旧代码将查询地址,即使数据库已迁移,它也会从 Person table 获取地址(这将是一个旧值,但假设这不是一个大问题)。
我现在如何安全地删除 _address
字段?如果我们将部署版本 3 并删除 _address
字段,那么版本 2 的代码仍将尝试在 select 上获取 _address
,即使它没有在任何地方使用并且会失败 "No such column" 例外。
有没有办法防止这种情况发生并在版本 2 的代码中将某些字段标记为 "non-fetchable"?所以版本 2 不会删除字段,但不会再获取它,版本 3 会删除字段。
是的,你可以做到:
QuerySet.defer():
"在一些复杂的数据建模情况下,您的模型可能包含很多字段,其中一些可能包含大量数据(例如,文本字段),或者需要昂贵的处理才能将它们转换为 Python 对象。如果您在某些情况下使用查询集的结果,而您在最初获取数据时不知道是否需要这些特定字段,则可以告诉 Django 不要从中检索它们数据库。 - docs
Entry.objects.defer("headline", "body")
或
从 django 1.8 开始:使用 values_list
. You can only include fields that you want. You can also use Queryset.only()
and Queryset.defer()
优化您的查询集查询。您也可以链接 defer()
调用
Entry.objects.values_list('id', 'headline')
您可以为 defer
您的所有查询集的特定 field/fields 使用自定义对象管理器。
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
字段。