Django 1.0 / 1.1 riscrivere il self join
Domanda
Esiste un modo per riscrivere questa query usando l'oggetto 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
Dove i voti sono una tabella, object_id è un int che si verifica più volte (chiave esterna - anche se non ha importanza qui) e creato_on che è un datetime.
FWIW, questa query consente di ottenere un punteggio in qualsiasi momento nel passato sommando tutti i voti precedenti su quell'oggetto_id.
Soluzione
Sono abbastanza sicuro che la query non possa essere creata con Django ORM. Il nuovo codice di aggregazione di Django è piuttosto flessibile, ma non credo che possa fare esattamente quello che vuoi.
Sei sicuro che la query funzioni? Sembra che manchi un controllo che b.object_id è 1.
Questo codice dovrebbe funzionare, ma è più di una riga e non è così efficiente.
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"]
L'aggregazione è disponibile solo nel trunk, quindi potrebbe essere necessario aggiornare l'installazione di django prima di poterlo fare.
Altri suggerimenti
Il problema non è l'aggregazione; il problema qui è che l'ORM di Django semplicemente non si unisce a nulla che non sia ForeignKey, AFAIK.
Questo è quello che sto usando ora. Ironia della sorte, il sql è rotto ma questo è l'essenza di esso:
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