2015-11-20 2 views
3

Как я могу использовать ORM Django для сортировки всех объектов в наборе запросов на основе условной совокупности связанных элементов? Django 1.8 и выше явно имеют conditional aggregation support, мне нужен ответ Django < 1.8. Это, очевидно, будет включать 3 или 4 запроса. Вот пример моделирует отвечающему можно использовать, чтобы проиллюстрировать ее ответ:Как отсортировать набор запросов Django путем условной агрегации связанных элементов?

class Group(models.Model): 
    owner = models.ForeignKey(User) 
    created_at = models.DateTimeField(auto_now_add=True) 

class GroupTraffic(models.Model): 
    visitor = models.ForeignKey(User) 
    which_group = models.ForeignKey(Group) 
    time_of_visit = models.DateTimeField(auto_now_add=True) 

пользователи собственных группы чата, и другие пользователи могут посетить указанные группы чата. Ответ на вопрос: как можно создать отсортированный список всех групп, так что он отсортирован по уникальным трафиком, который каждая группа просмотрела в последние 60 минут? Группы, которые видели множество уникальных посетителей за последние 60 минут, сортируются вверх, группы с почти нулевым (или нулевым) таким движением появляются в нижней части списка.

Это условный вопрос об агрегировании, потому что по существу нам необходимо аннотировать каждый объект группы, граф всех связанных уникальных объектов grouptraffic, которые были зарегистрированы в течение последних 60 минут.

Может кто-нибудь показать мне, как использовать Django ORM для решения этой проблемы для < 1.8? Я уже знаю, как это сделать для> = 1.8 посредством условной агрегации (спасибо this), и я не хочу делать это с помощью SQL-запросов в raw или extra.

+0

По уникальному трафику я имею в виду не двойной счет, если это посетитель с тем же идентификатором. То есть используя 'distinct' в ORM Django. –

+0

Какие вопросы вы пробовали? –

+0

Огромный человек списка, держись, я поставлю некоторые из ближайших здесь. –

ответ

2

Просто фильтр на time_of_visit и он должен работать нормально:

one_hour_ago = datetime.now()-timedelta(hours=1) 
recent_groups = Group.objects.filter(grouptraffic__time_of_visit>=one_hour_ago) 
visitors = recent_groups.annotate(views=Count('grouptraffic__visitor', distinct=True)) 

Затем получить все из старших групп, с extra поле для пустых просмотров:

older_groups = Group.objects.filter(grouptraffic__time_of_visit < one_hour_ago).extra(select={'visits':0}) 

Тогда сцепить их вместе с трубой:

all_groups = visitors | older_groups 
+0

Не будет ли это * не включать * группы, которые не регистрировали посещение за последний час? Я хочу включить все группы, только те, кто не посещает последний час, должны быть отсортированы последними. –

+0

Хорошо, и еще одно требование сортирует список по * hottest * group first. Я должен сразу запустить "order_by ('- views')" on "all_groups" в конце ?. –

+0

Это должно сработать. Если нет, вы можете отсортировать каждый запрос самостоятельно и затем слить. –

Смежные вопросы