一个例子胜于千言万语:
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
它是否故意这样工作?
子问题:是否有任何简单的方法可以从延迟的模型中获取常规模型实例?
编辑:
看起来contenttypes框架已正确修补: http://code.djangoproject.com/changeset/10523
所以我会说Model ._____ eq _____()运算符看起来应该不像this:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
但更像是这样:
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()
这当然首次导致两次DB命中,但幸运的是get_for_model似乎实现了缓存。
答案 0 :(得分:2)
延迟查询返回由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.
"""
它基本上是一个代理,您可以从方法解析顺序中看到:
>>> 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'>)
答案 1 :(得分:0)
它的正常行为,因为User.objects.filter(id = 19)[0]将返回一个包含模型所有相关字段的查询集,但User.objects.filter(id = 19).defer( 'email')[0]会带一个没有电子邮件的查询集...所以你有两个查询集,一个字段较少。
更新
...测试
In [30]: a = User.objects.filter(id=1)[0]
In [31]: a
Out[31]: <User: mustafa>
In [27]: b = User.objects.filter(id=1).defer('username')[0]
In [28]: b
Out[28]: <User_Deferred_username: mustafa>
In [32]: a == b
Out[32]: False
In [33]: type(a)
Out[33]: <class 'django.contrib.auth.models.User'>
In [34]: type(b)
Out[34]: <class 'django.contrib.auth.models.User_Deferred_username'>
In [35]: a.username
Out[35]: u'mustafa'
In [36]: b.username
Out[36]: u'mustafa'
Defer Documentation将此解释为:
具有延迟字段的查询集仍将返回模型实例。如果您访问该字段(一次一个,而不是一次所有延迟字段),将从数据库中检索每个延迟字段。
编辑2:
In [43]: isinstance(b, a.__class__)
Out[43]: True
In [40]: User.__eq__??
Type: instancemethod
Base Class: <type 'instancemethod'>
String Form: <unbound method User.__eq__>
Namespace: Interactive
File: /home/mustafa/python/lib/django/db/models/base.py
Definition: User.__eq__(self, other)
Source:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
==是一个简单的比较,它比较两个对象,它没有使用相关的类____eq____方法。