Tom*_*ski 6 python django orm django-models
一个例子胜过千言万语:
In [3]: User.objects.filter(id=19)[0] == User.objects.filter(id=19)[0]
Out[3]: True
In [4]: User.objects.filter(id=19)[0] == User.objects.filter(id=19).defer('email')[0]
Out[4]: False
Run Code Online (Sandbox Code Playgroud)
它故意这样工作吗?
子问题:是否有任何简单的方法可以从延迟模型中获取常规模型实例?
编辑:
看起来contenttypes框架已正确修补:http://code.djangoproject.com/changeset/10523
所以我会说Model ._____ eq _____()运算符不应该是这样的:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
Run Code Online (Sandbox Code Playgroud)
但更像这样:
def __eq__(self, other):
return ContentType.objects.get_for_model(self) is ContentType.objects.get_for_model(other) and self._get_pk_val() == other._get_pk_val()
Run Code Online (Sandbox Code Playgroud)
这当然首次导致两次DB命中,但幸运的是get_for_model似乎实现了缓存.
延迟查询返回不同的类,由以下提供deferred_class_factory:
# in db/models/query_utils.py
def deferred_class_factory(model, attrs):
"""
Returns a class object that is a copy of "model" with the specified "attrs"
being replaced with DeferredAttribute objects. The "pk_value" ties the
deferred attributes to a particular instance of the model.
"""
Run Code Online (Sandbox Code Playgroud)
它基本上是一个代理,从方法解析顺序可以看出:
>>> x = User.objects.filter(id=1).defer("email")[0]
>>> x.__class__.__mro__
(<class 'django.contrib.auth.models.User_Deferred_email'>, \
<class 'django.contrib.auth.models.User'>, \
<class 'django.db.models.base.Model'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)