Django 1.0 / 1.1 переписать самостоятельно присоединиться

StackOverflow https://stackoverflow.com/questions/612204

  •  03-07-2019
  •  | 
  •  

Вопрос

Есть ли способ переписать этот запрос с помощью объекта 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top