2009-03-07 6 views
16

Tengo una tabla con un IntegerField (hit_count), y cuando se visita una página (por ejemplo, http://site/page/3) Quiero ID de registro columna de 3 hit_count en la base de datos que hay que sumar 1.Incremento Página de aciertos en Django

La consulta debe ser como:

update table set hit_count = hit_count + 1 where id = 3 

¿Puedo hacer esto con las convenciones estándar de Django modelo? ¿O debería simplemente escribir la consulta a mano?

+0

Ayuda si proporciona el modelo en sí. –

+0

Posible duplicado de [Incremento atómico de un contador en django] (http://stackoverflow.com/questions/1598932/atomic-increment-of-a-counter-in-django) –

Respuesta

31

Si utiliza Django 1.1+, sólo tiene que utilizar F expressions:

from django.db.models import F 
... 
MyModel.objects.filter(id=...).update(hit_count=F('hit_count')+1) 

Esto realizará una sola consulta a la base atómica.

Como dice gerdemb, deberías considerar poner esto en un middleware para que sea fácilmente reutilizable para que no ocupe todos tus puntos de vista.


+1

+1: http://docs.djangoproject.com/en/dev/topics/db/queries/#filters-can-reference-fields-on-the-model –

+0

Gracias: tenía que enlazar a eso, pero se olvidó. Lo agregaré –

+1

Lo que creo que quieres es 'MyModel.objects.get (id = ...)' en lugar de 'filter'; si sabemos que es una sola fila, ¿por qué no dejarlo en claro? –

0

Las convenciones del modelo no serán atómicas; escribir a mano:

BEGIN 
SELECT * FROM table WHERE id=3 FOR UPDATE 
UPDATE table SET hit_count=hit_count+1 WHERE id=3 
COMMIT 
+1

El ORM de Django tiene soporte para esta consulta (en tronco, y luego v1.1) - no necesita escribirlo a mano. –

0

Me gustaría empezar por mirar la documentación de middleware. El comentario de Ignacio sobre la falta de transacciones atómicas es cierto, pero este es un problema con todo el marco de Django. A menos que esté preocupado por tener un contador 100% preciso, no me preocuparía.

+0

¿Cómo es esto un "problema con todo el framework de Django?" Puede realizar transacciones atómicas por solicitud con TransactionMiddleware u obtener un control más detallado con las funciones en django.db.transaction. –

+0

Claro que puede tener transacciones, pero no están habilitadas por defecto. Si construyes una aplicación CRUD simple usando el administrador de Django incorporado, vas a tener condiciones de carrera. Incluso el tutorial en la documentación de Django tiene este tipo de problemas. – user27478

+0

La forma en que lo ha redactado hace que suene como un problema inevitable, que, por supuesto, confunde a alguien que tal vez no conozca tanto acerca de Django como usted. – Jordan

4

Como dice gerdemb, debe escribirlo en un middleware para hacerlo realmente reutilizable. O (más simple) escribe un decorador de función. De hecho, hay adaptadores para usar un middleware como decorador y viceversa.

Pero si le preocupa el rendimiento y desea mantener bajas las consultas de DB por página, puede usar la operación de incremento atómico de memcached. por supuesto, en este caso, debes cuidarte de la persistencia.

+0

Para un buen rendimiento, la solución de memcached es la mejor, pero es más complicada. –

Cuestiones relacionadas