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.

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top