我有两个Django模型
class ValidName:
name = models.TextField()
class MetaSyntacticName(ValidNames):
name = models.ForeignKey(ValidName)
usages = models.IntegerField()
如果我有一个MetaSyntacticName实例,是否可以找出它的名称引用的ValidName实例是否从数据库中加载而无需数据库查询?
答案 0 :(得分:0)
如果您调用select_related,那么将不需要任何额外的数据库查询来预填充与ForeignKey相关的对象。例如:(从文档粘贴的副本):
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
这是select_related查找:
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
答案 1 :(得分:0)
您可以添加如下方法:
class MetaSyntacticName(ValidNames):
...
def valid_name_is_cached(self):
return __class__.validname_ptr.is_cached(self)
__ class__只是MetaSyntacticName
validname_ptr-是具有方法is_cached的Django描述符
答案 2 :(得分:0)
我可以找到的一种方法是使用私有模型实例属性_state
。它具有属性fields_cache
,它是一个映射:字段名->字段缓存。
因此,根据您的情况,您可以使用以下行检查是否已加载外键name
:
'name' in instance._state.fields_cache
其中instance
是MetaSyntacticName
的实例。
以下代码演示了它的工作原理:
foo = ValidName.objects.create(name='foo')
foo_meta = MetaSyntacticName.objects.create(name=foo, usages=1)
'name' in foo_meta._state.fields_cache # True
foo_meta = MetaSyntacticName.objects.get(name_id=foo.id)
'name' in foo_meta._state.fields_cache # False
# next line hits the db and loads the field 'name'
foo_meta.name
'name' in foo_meta._state.fields_cache # True
我花了一些时间来破解它,所以我希望这可以节省别人的时间:)
P.S。我检查了类似的代码是否可以在Django 2.2上正常工作,因为_state
是一个私有属性,在Django版本之间可能有所不同