这些查询之间是否有任何区别:
category, _ = models.Category.objects.get_or_create(
title=some_title,
brick=node_id,
parent=parent,
)
和
category, _ = models.Category.objects.defer('data').get_or_create(
title=some_title,
brick=node_id,
parent=parent,
)
?
类别模型如下所示:
class Category(Model):
title = models.CharField(max_length=255, blank=True, null=True)
brick = models.IntegerField(
primary_key=True,
)
parent = models.ForeignKey('self', blank=True, null=True)
data = models.TextField(blank=True, null=True) # very large text
答案 0 :(得分:1)
这主要是按照您的预期运作。
从db中检索对象时,defer不会选择该字段,但请注意,即使该字段被延迟,也可以在get查询的WHERE
子句中查看该对象必须被创造(正如人们所期望的那样)。如果该对象不可用,则会发出第二个INSERT
,插入get_or_create
方法中指定的所有字段,甚至是最终在defer
调用中指定的字段。
唯一令人讨厌的是创建一个尚不存在的对象而你没有在get_or_create
中指定一个你defer
的字段,就像你的情况一样,然后尝试在创建的对象上访问此特定字段,生成一个额外的(第三个)查询以从db中获取该字段(即使我们知道它不存在)。
# Model has fields a and b, b being optional
a, c = Model.objects.defer('b').get_or_create(a=1) # Two queries, one to get, the second to insert (ignore that sqlite does 3 queries here)
# c is True
# a is now a deferred object
a.a # doesn't hit the db again
a.b # hits the db trying to retrieve the b field
如果您插入该对象,而不指定延迟或可选字段,则不会在第三次尝试在创建的对象上获取该可选字段时命中数据库。
# Model has fields a and b, b being optional
a, c = Model.objects.get_or_create(a=1) # Two queries as before
# c is True
# a is NOT a deferred object
a.a # doesn't hit the db
a.b # no db hit, b being empty
另一种情况是您使用延迟字段加载对象并尝试保存此对象的情况,documentation表示:
为具有延迟字段的实例调用save()时,仅保存已加载的字段。有关详细信息,请参阅save()。