Django QuerySet .defer()问题 - 错误还是功能?

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似乎实现了缓存.

mik*_*iku 4

延迟查询返回不同的类,由以下提供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)