Django:检查是否已加载外键字段

时间:2018-12-08 03:34:41

标签: django django-models

我有两个Django模型

class ValidName:
    name = models.TextField()

class MetaSyntacticName(ValidNames):
    name = models.ForeignKey(ValidName)
    usages = models.IntegerField()

如果我有一个MetaSyntacticName实例,是否可以找出它的名称引用的ValidName实例是否从数据库中加载而无需数据库查询?

3 个答案:

答案 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

其中instanceMetaSyntacticName的实例。

以下代码演示了它的工作原理:

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版本之间可能有所不同