Django 1.0/1.1 Reescrita de auto -junção
Pergunta
Existe uma maneira de reescrever esta consulta usando o 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
Onde os votos são uma tabela, object_id é um int que ocorre várias vezes (chave estrangeira - embora isso não importa aqui) e criado_on, que é um tempo de dados.
FWIW, essa consulta permite obter uma pontuação a qualquer momento no passado, resumindo todos os votos anteriores nesse objeto_id.
Solução
Tenho certeza de que a consulta não pode ser criada com o Django Orm. O novo código de agregação do Django é bastante flexível, mas acho que não pode fazer exatamente o que você deseja.
Tem certeza de que a consulta funciona? Você parece estar perdendo uma verificação de que B.Object_Id é 1.
Esse código deve funcionar, mas é mais de uma linha e não tão 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"]
A agregação está disponível apenas no tronco, portanto, você pode precisar atualizar sua instalação do Django antes de poder fazer isso.
Outras dicas
Agregação não é o problema; O problema aqui é que o ORM do Django simplesmente não se une a nada que não seja uma chave estrangeira, Afaik.
É isso que estou usando agora. Ironicamente, o SQL está quebrado, mas esta é a essência dele:
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