Python Django';当访问外来对象时,ORM将设法获取这些对象

Python Django';当访问外来对象时,ORM将设法获取这些对象,python,django,orm,Python,Django,Orm,我花了几个小时想弄明白这一点,但一无所获 class other(models.Model): user = models.ForeignKey(User) others = other.objects.all() o = others[0] 此时,ORM没有请求o.user对象,但如果我做了任何涉及该对象的操作,它会从数据库中加载该对象 type(o.user) 将导致从数据库加载 type(o.user) 我想了解的是他们是如何变魔术的。是什么导致了这种情况的发生。是的,我

我花了几个小时想弄明白这一点,但一无所获

class other(models.Model):
    user = models.ForeignKey(User)


others = other.objects.all()
o = others[0]
此时,ORM没有请求o.user对象,但如果我做了任何涉及该对象的操作,它会从数据库中加载该对象

type(o.user)
将导致从数据库加载

type(o.user)
我想了解的是他们是如何变魔术的。是什么导致了这种情况的发生。是的,我已经查看了源代码,我被难住了。

这并不能解释Django到底是如何进行的,但您看到的是延迟加载。延迟加载是一种众所周知的设计模式,它将对象的初始化推迟到需要的时候。在您的情况下,直到执行
o=others[0]
type(o.user)
之一。这可能会让你对这个过程有一些了解

Django使用()自定义模型类的创建。对于在模型上定义为类属性的每个对象(
user
是我们关心的对象),Django首先查看它是否定义了一个
contribution\u to\u class
方法。如果定义了该方法,Django将调用它,从而允许对象在创建模型类时自定义模型类。如果对象没有定义
contribution\u to\u class
,则只需使用
setattr
将其分配给类即可

由于
ForeignKey
是Django模型字段,因此它定义了。当
ModelBase
元类调用
ForeignKey.contribution\u to\u class
时,分配给
ModelClass.user
的值是的实例

ReverseSingleRelatedObjectDescriptor
是一个实现Python的对象,用于自定义当类的实例作为另一个类的属性访问时发生的情况。在这种情况下,描述符用于在第一次访问数据库时从数据库返回相关的模型实例

# make a user and an instance of our model
>>> user = User(username="example")
>>> my_instance = MyModel(user=user)

# user is a ReverseSingleRelatedObjectDescriptor
>>> MyModel.user
<django.db.models.fields.related.ReverseSingleRelatedObjectDescriptor object>

# user hasn't been loaded, yet
>>> my_instance._user_cache
AttributeError: 'MyModel' object has no attribute '_user_cache'

# ReverseSingleRelatedObjectDescriptor.__get__ loads the user
>>> my_instance.user
<User: example>

# now the user is cached and won't be looked up again
>>> my_instance._user_cache
<User: example>
#创建我们模型的用户和实例
>>>用户=用户(用户名=“示例”)
>>>my_实例=MyModel(用户=用户)
#用户是ReverseSingleRelatedObjectDescriptor
>>>MyModel.user
#用户尚未加载
>>>我的\u实例。\u用户\u缓存
AttributeError:“MyModel”对象没有属性“\u user\u cache”
#ReverseSingleRelatedObjectDescriptor.\uuu获取\uuuuu加载用户
>>>my_instance.user
#现在,用户已被缓存,不再进行查找
>>>我的\u实例。\u用户\u缓存

reversesingrelatedObjectDescriptor.\uuuu get\uuuu
方法在每次对模型实例访问
user
属性时都会被调用,但它足够聪明,只需查找一次相关对象,然后在后续调用时返回缓存版本。

属性可用于实现此行为。基本上,您的类定义将生成一个类似于以下内容的类:

class other(models.Model):
    def _get_user(self):
        ## o.users being accessed
        return User.objects.get(other_id=self.id)

    def _set_user(self, v):
        ## ...

    user = property(_get_user, _set_user)

在您访问“其他”实例的.User之前,不会执行对User的查询。

是的,我理解原因,我正在寻找他们是如何完成此操作的解释。有没有简单的方法强制缓存相关对象?我在Google上搜索了django.db.models.fields.related.ReverseSingleRelatedObjectDescriptor,找到了这篇文章……你是在尝试预填充缓存吗?我想这可能就是你要找的。如果您试图使缓存无效,我认为最好的办法就是删除模型实例上的cache属性。