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.

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top