Django 1.0 / 1.1 переписать самостоятельно присоединиться
Вопрос
Есть ли способ переписать этот запрос с помощью объекта 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
Там, где голосования - это таблица, object_id - это int, который встречается несколько раз (внешний ключ - хотя это не имеет значения), а create_on - это datetime.
FWIW, этот запрос позволяет в любое время получить оценку, суммируя все предыдущие голоса по этому object_id.
Решение
Я почти уверен, что запрос нельзя создать с помощью Django ORM. Новый код агрегации Django довольно гибкий, но я не думаю, что он может делать именно то, что вы хотите.
Вы уверены, что запрос работает? Похоже, вы пропустили проверку того, что b.object_id равен 1.
Этот код должен работать, но он состоит из нескольких строк и не настолько эффективен.
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"]
Агрегирование доступно только в транке, поэтому вам может потребоваться обновить установку django, прежде чем вы сможете это сделать.
Другие советы
Агрегация не проблема; проблема здесь в том, что ORM в Django просто не выполняет соединения с чем-то, что не является ForeignKey, AFAIK.
Это то, что я сейчас использую. По иронии судьбы, sql не работает, но это суть этого:
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