2010-04-21 44 views
35

Estoy buscando una manera simple pero recomendada en Django para almacenar una variable en memoria solamente. Cuando Apache se reinicia o el servidor de desarrollo Django se reinicia, la variable vuelve a cero. Más específicamente, quiero contar cuántas veces tiene lugar una acción en particular en cada instancia del modelo (registro de la base de datos), pero por motivos de rendimiento, no lo hago. Quiero almacenar estos conteos en la base de datos. No me importa si los recuentos desaparecen después de reiniciar el servidor. Pero mientras el servidor esté activo, quiero que estos recuentos sean consistentes entre el shell de Django y la interfaz web, y deseo poder devolver cuántas veces se ha realizado la acción en cada instancia del modelo.Python Django Global Variables

No deseo que las variables se asocien con un usuario o sesión porque podría querer devolver estos conteos sin haber iniciado sesión (y quiero que los recuentos sean consistentes sin importar qué usuario haya iniciado sesión). ¿Estoy describiendo una variable global? Si es así, ¿cómo uso uno en Django? Me he dado cuenta de que los archivos como urls.py, settings.py y models.py parecen procesarse solo una vez por cada inicio del servidor (por contraste con views.py que parece procesarse cada vez que se realiza una solicitud). ¿Esto significa que debo declarar mis variables en uno de esos archivos? ¿O debería almacenarlo en un atributo de modelo de alguna manera (siempre que permanezca mientras el servidor esté funcionando)? Esta es probablemente una pregunta fácil, pero no estoy seguro de cómo se hace en Django.

Cualquier comentario o consejo es muy apreciado. Gracias, Joe

+0

Los documentos de almacenamiento en caché están un poco "en memoria caché por página". Vaya a "bajo nivel" para obtener detalles sobre cómo usarlo para las variables del servidor: https://docs.djangoproject.com/en/1.3/topics/cache/#the-low-level-cache-api –

+0

Esto podría ayudarlo: [https://github.com/andres-torres-marroquin/django-system-globals](https://github.com/andres-torres-marroquin/django-system-globals) –

Respuesta

24

Usted no debe declarar variables globales. Las configuraciones (constantes) son correctas si se hacen bien. Pero las variables infringen con shared-nothing arquitectura y pueden causar muchos problemas. (en el mejor de los casos, serán inconsistentes)

Simplemente almacenaría esas estadísticas en el caché. (Bueno, en realidad me almacenarlos en la base de datos pero se hizo claro que creer que tendrá un impacto negativo en el rendimiento, así que ...)

Los nuevos incr() y decr() métodos son especialmente adecuados para el conteo. Ver docs para más información.

+3

+1 para almacenar estos en el caché –

+0

Me gusta este enfoque y lo estoy implementando.Actualmente estoy usando localmem para el backend de caché en el servidor de desarrollo Django y he notado que los conteos no persisten después de navegar a través de varias páginas web en mi sitio. (En cuyo momento NO reinicié el servidor de desarrollo django) me doy cuenta de que puede haber múltiples razones para esto. (Eventualmente usaré memcached). Me pregunto si el servidor de desarrollo de caché de localmem/django no conserva los valores almacenados en caché durante mucho tiempo o si de algún modo tengo una configuración incorrecta. –

+0

@Joe: siempre uso la memoria caché de db en ausencia de un backend de memoria caché adecuado como memcached. Sólo para estar seguro. Esto va de la mano con "no preocuparse en absoluto por los problemas de rendimiento hasta que sean evidentes" y "medir antes de optimizar". – muhuk

54

¿Por qué uno no debe declarar variables globales? O_o. Simplemente parece una propaganda. Si el autor sabe lo que quiere y cuáles serán los efectos secundarios, ¿por qué no? Quizás es solo un experimento rápido.

Puede declarar su contador como un modelo clase-miembro. Luego, para tratar con la condición de carrera, debes agregar un método que esperará si otro cliente, desde otro hilo, funciona con el contador. Algo como esto:

import threading 

class MyModel(ModelBase): 
    _counter = 0 
    _counter_lock = threading.Lock() 

    @classmethod 
    def increment_counter(cls): 
     with cls._counter_lock: 
      cls._counter += 1 

    def some_action(self): 
     # core code 
     self.increment_counter() 


# somewhere else 
print MyModel._counter 

recordar sin embargo: usted tiene que tener su aplicación en un proceso de . Por lo tanto, si implementó la aplicación en Apache, asegúrese de que esté configurada para engendrar muchos hilos, pero no muchos procesos. Si está experimentando con ./manage.py run, no se requieren acciones.

+1

Esto es exactamente lo que quiero. Necesito generar una identificación de serie que se incrementaría para cada solicitud con fines de prueba. En el sistema actual, la identificación proviene de una API externa. – k4ml

+2

Esto podría ser un enfoque viable para proyectos de juguetes. Pero una vez que empiezas a usar esta clase, garantizas que tu aplicación no es escalable. Hay una razón por la cual tenemos el subsistema de caché. – muhuk

+1

utilicé este enfoque para ejemplificar una vez que un cliente a un servicio de máquina, ejemplificarlo cada vez más lento mi servidor web ... – thrantir

Cuestiones relacionadas