2009-12-11 30 views
20

En mi aplicación Django, ejecuto repetidamente la misma consulta en mi base de datos (por ejemplo, cada 10 segundos). Luego creo una suma de MD5 sobre el conjunto de preguntas que recibo y comparo eso con la suma de MD5 que creé en la ejecución anterior. Si ambos son iguales, los datos no han cambiado y la página web no necesita actualización.Cómo deshabilitar el caché de consultas de Django?

Mientras hago esto, los datos en la base de datos pueden cambiar.

Sin embargo, la consulta devuelve el mismo queryset, aparentemente debido a query caching.

¿Cómo puedo desactivar el caché de consultas y ejecutar explícitamente la consulta en el DB?

+0

duplicado posible de [¿Cómo fuerzo Django hacer caso omiso de cualquier caché y volver a cargar los datos?] (Http://stackoverflow.com/questions/3346124/how-do-i-force- django-to-ignore-any-caches-and-reload-data) –

Respuesta

41

Me encontré con el comportamiento que pensé que era una especie de almacenamiento en caché, pero resultó ser que las transacciones de la base de datos me engañaban.

que tenían el problema de que en otro proceso, los elementos se se añaden a la base de datos, y quería para monitorear el progreso del otro proceso, por lo que abrió una cáscara de Django y emitió la siguiente:

>>> MyData.objects.count() 
74674 

>>> MyData.objects.count() 
74674 

El valor no cambiaba, aunque realmente estaba en la base de datos. Me di cuenta de que al menos con la forma en que tenía MySQL & configuración django que estaba en una transacción y solo vería una "instantánea" de la base de datos en el momento en que abrí la transacción.

Dado que con las vistas en django, tenía el comportamiento de autocommitido definido, esto estaba bien para que cada vista solo vea una instantánea, ya que la próxima vez que se llamara a una vista sería en una transacción diferente. Pero para un fragmento de código que no se estaba confirmando automáticamente, no vería ningún cambio en el db, excepto los que se realizaron en esta transacción.

Sólo pensé en arrojar esta respuesta para cualquier persona que pueda encontrarse con esta situación.

de resolver, de comprometer su operación, lo cual puede hacerse manualmente, así:

>> from django.db import transaction 
>> transaction.enter_transaction_management() 
>> transaction.commit() # Whenever you want to see new data 
+2

Muchas gracias, obtuve este comportamiento exacto cuando ejecuto un comando que escucha una cola y debo procesar algunos eventos, cuando eso sucedía, el procesador no encontraba usuarios creados después de que el comando comenzara a ejecutarse – victorcampos

+1

A 'transaction.commit_unless_managed()' también funcionó para mí –

+1

¡Respuesta perfecta para un problema que encontré molesto tantas veces en el pasado! Gracias una tonelada. – Sarang

6

El enlace que se crea la documentación de Django implica que la siguiente:

>>> print [e.headline for e in Entry.objects.all()] 
>>> print [e.pub_date for e in Entry.objects.all()] 

crea dos consultas a la base de datos, mientras que:

>>> queryset = Poll.objects.all() 
>>> print [p.headline for p in queryset] # Evaluate the query set. 
>>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation. 

utiliza la caché de consultas, ya que está accediendo a la mismos resultados de evaluación.

9

El almacenamiento en caché de consultas solo aplica dentro de un QuerySet. En otras palabras, si evalúa dos veces el mismo objeto de conjunto de consulta, funcionará el almacenamiento en caché de consultas. Pero si está haciendo una consulta cada 10 segundos, presumiblemente esto es a través de un cron que genera un nuevo proceso cada vez, por lo que no hay forma de que Django guarde en caché nada.

Es posible que el propio caché de su base de datos entre en funcionamiento si repetidamente realiza exactamente la misma consulta. Debería ver la documentación de su DBMS para ver cómo administrarla correctamente.

+1

Si bien es correcto, esto no responde la pregunta que apunta claramente a django queryset. La respuesta de @kekoa coincide con la pregunta de OP. – sberder

1

Muchas gracias por sus respuestas, sus respuestas me hicieron dar unos pasos atrás y volver a pensar.

Para probar el almacenamiento en caché en un nivel DBMS, me alejé de Django y utilicé un script de shell que de todos modos tuve a mano para consultar datos de un DB de SQLite, mientras añadía datos en una segunda sesión de shell. Los nuevos datos aparecieron en las consultas periódicas justo después de que los agregué, por lo que no hay caché de consultas aquí.

Esto se redujo a la parte de Django. El código involucrado no es muy complejo y una pequeña salida de registro y una revisión del código revelaron el problema: la consulta utilizada para obtener el conjunto de consulta usado para crear la suma MD5 tenía un error y siempre estaba vacía. Por lo tanto, la suma de MD5 siempre fue la misma. De hecho, parecía un resultado en caché: los datos están cambiando, pero el conjunto de preguntas permanece igual. El problema no se muestra en la aplicación, ya que se utilizó una consulta diferente para obtener los datos que allí se muestran.

Lección aprendida: Si está completamente perplejo, retroceda un paso y vuelva a pensar en sus suposiciones.

¡Gracias nuevamente! :-)

0

me encontré con este problema en la versión 1.8 de Django. No hay una manera directa de hacerlo, pero hay algunas maneras de hacer que el conjunto de consulta se reevalúe y ejecute accediendo a db en lugar de a la caché. Lo encontré en Django Queryset Documentation

Utilicé uno de ellos para manejar mi problema. Es la función exists() de los conjuntos de consulta. len() y repr() también se pueden utilizar. Ellos trabajaron para mí también.

Ejemplo

queryset = ModelClass.objects.filter(....) 
queryset.exists() 

#or len(queryset) 
#or repr(queryset) 

#Now queryset is re-evaluated. 
Cuestiones relacionadas