Django 1.0 / 1.1 reescritura de auto-unión
Pregunta
¿Hay alguna forma de volver a escribir esta consulta utilizando el objeto Django QuerySet:
SELECT b.created_on, SUM(a.vote)
FROM votes a JOIN votes b ON a.created_on <= b.created_on
WHERE a.object_id = 1
GROUP BY 1
Cuando votos es una tabla, object_id es un int que se produce varias veces (clave externa, aunque eso no importa aquí), y created_on que es una fecha y hora.
FWIW, esta consulta permite obtener una puntuación en cualquier momento en el pasado al resumir todos los votos anteriores en ese object_id.
Solución
Estoy bastante seguro de que la consulta no se puede crear con el ORM de Django. El nuevo código de agregación de Django es bastante flexible, pero no creo que pueda hacer exactamente lo que quieres.
¿Estás seguro de que la consulta funciona? Parece que te falta un control de que b.object_id es 1.
Este código debería funcionar, pero es más de una línea y no es tan eficiente.
from django.db.models import Sum
v_list = votes.objects.filter(object__id=1)
for v in v_list:
v.previous_score = votes.objects.filter(object__id=1, created_on__lte=v.created_on).aggregate(Sum('vote'))["vote__sum"]
La agregación solo está disponible en el troncal, por lo que es posible que deba actualizar su instalación de django antes de poder hacer esto.
Otros consejos
La agregación no es el problema; El problema aquí es que el ORM de Django simplemente no hace uniones en nada que no sea un ForeignKey, AFAIK.
Esto es lo que estoy usando ahora. Irónicamente, el sql está roto pero esto es lo esencial:
def get_score_over_time(self, obj):
"""
Get a dictionary containing the score and number of votes
at all times historically
"""
import pdb; pdb.set_trace();
ctype = ContentType.objects.get_for_model(obj)
try:
query = """SELECT b.created_on, SUM(a.vote)
FROM %s a JOIN %s b
ON a.created_on <= b.created_on
WHERE a.object_id = %s
AND a.content_type_id = %s
GROUP BY 1""" % (
connection.ops.quote_name(self.model._meta.db_table),
connection.ops.quote_name(self.model._meta.db_table),
1,
ctype.id,
)
cursor = connection.cursor()
cursor.execute(query)
result_list = []
for row in cursor.fetchall():
result_list.append(row)
except models.ObjectDoesNotExist:
result_list = None
return result_list