queries python django orm django-models

python - orm django queries



Problema de Django QuerySet.defer()-¿error o característica? (2)

Es el comportamiento normal, porque User.objects.filter (id = 19) [0] devolverá un conjunto de consulta con todos los campos relacionados del modelo, pero User.objects.filter (id = 19) .defer (''email'' ) [0] traerá un conjunto de consulta sin correo electrónico ... Por lo tanto, tiene dos conjuntos de consulta, uno con un campo menor.

Actualizar:

Prueba...

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''

La documentación de aplazamiento explica esto como:

Un conjunto de consulta que tiene campos diferidos todavía devolverá instancias de modelo. Cada campo diferido se recuperará de la base de datos si accede a ese campo (uno a la vez, no todos los campos diferidos a la vez).

EDICION 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()

== es una comparación simple y compara dos objetos, no está usando el método de la clase relacionada ____eq____.

Un ejemplo es mejor que mil palabras:

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

Funciona así a propósito?

Subjetivo: ¿hay alguna manera simple de obtener una instancia de modelo regular de la diferida?

EDITAR:

Parece que el framework contenttypes está parcheado apropiadamente: http://code.djangoproject.com/changeset/10523

entonces yo diría que el operador Modelo ._____ eq _____ () no debería verse así:

def __eq__(self, other): return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()

pero más como esto:

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()

Esto, por supuesto, causa dos hits DB por primera vez, pero afortunadamente get_for_model parece implementar el caché.


Las consultas diferidas devuelven una clase diferente, proporcionada por el 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. """

Básicamente es un proxy, como se puede ver en el orden de resolución del método:

>>> 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''>)