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.

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top