Django: как сделать заказ на связанное поле смежного поля

Я использую аннотацию, чтобы добавить свойство к объекту, которое затем я могу использовать для order_by. Тем не менее, я хочу аннотировать поле отношения в отношении. Я знаю, что должен быть в состоянии как-то добраться до поля, используя двойное подчеркивание, но я просто не могу обернуться вокруг него.

Вот модели:

class Group(Taggable, Uploadable):
    name            = models.CharField(max_length=250, db_index=True)
    description     = models.TextField(max_length=5000, null=True,
                        blank=True, db_index=True)
    private         = models.BooleanField(default=False)
    members         = models.ManyToManyField(User, null=True,
                        related_name='members', through='GroupToUser')
    pending_members = models.ManyToManyField(User, null=True,
                        related_name='pending_members')
    admin           = models.ForeignKey(User, null=True)
    timestamp       = models.DateTimeField(auto_now_add=True)
    author          = models.ForeignKey(User, related_name='author')

class Discussion(Taggable, Uploadable):
    author      = models.ForeignKey(User)
    title       = models.CharField(max_length=250, db_index=True)
    description = models.TextField(max_length=5000, null=True,
                    blank=True, db_index=True)
    group       = models.ForeignKey(Group, null=True)
    timestamp   = models.DateTimeField(auto_now_add=True)

class DiscussionResponse(Uploadable):
    author     = models.ForeignKey(User)
    discussion = models.ForeignKey(Discussion)
    message    = models.TextField(max_length=5000)
    timestamp  = models.DateTimeField(auto_now_add=True)

Таким образом, Обсуждение может быть необязательно связано с Группой, а Ответы на Обсуждение связаны с обсуждением. То, что я хотел бы сделать, - это найти самую последнюю дискуссионную версию ответов на любые обсуждения, связанные с группой, если она существует, и отсортировать по ней.

Я дошел до этого:

Group.objects.filter(some_filtering).distinct().annotate(
    last_response=Max('some__reverse__relationship__timestamp').order_by(
        '-last_response')

Я просто не могу найти правильный способ добраться до отметки времени на Response для обсуждения в этом случае.

ОБНОВЛЕНИЕ: Вы действительно можете заказать по аннотированному значению. Вот пример с order_by на отметке времени соответствующего обсуждения:

>>> groups = Group.objects.all().annotate(
        last_response=Max('discussion__timestamp')).order_by('-last_response')
>>> for group in groups:
...     print(group.id, group.last_response)
...     
... 
(2L, datetime.datetime(2013, 5, 8, 15, 32, 31))
(1L, None)
(3L, None)
(4L, None)
(6L, None)
(7L, None)
(8L, None)
(9L, None)

В этом случае только группа № 2 имела связанные обсуждения, поэтому она была перенесена наверх; остальные сохраняют естественный порядок. Что я действительно хотел бы сделать, так это переместить группы, чьи недавние ответы на обсуждения были перемещены в верхнюю часть списка. Вот почему я подумал 'discussion__discussionresponse__timestamp' будет работать, но это не так.

1 ответ

Решение

Ок, видимо это просто 'discussion__discussionresponse__timestamp', Я попробовал это в оболочке Django, и после сохранения нового DiscussionResponse это не сработало, но через несколько минут сработало, когда я попробовал снова:

>>> groups = Group.objects.all().annotate(last_response=Max(
        'discussion__discussionresponse__timestamp')).order_by('-last_response')
>>> for group in groups:
...     print(group.id, group.last_response)
...     
... 
(2L, datetime.datetime(2013, 5, 16, 14, 56, 22))
(1L, None)
(3L, None)
(4L, None)
(6L, None)
(7L, None)
(8L, None)
(9L, None)
>>> 

Если кто-то знает, почему он не работал сразу после сохранения нового объекта в базе данных, но работал позже, это, вероятно, будет полезной информацией.

Вот еще один прогон запроса с обсуждениями / ответами, добавленными в другую группу только для дополнительной проверки:

>>> groups = Group.objects.all().annotate(last_response=Max('discussion__discussionresponse__timestamp')).order_by('-last_response')
>>> for group in groups:
...     print(group.id, group.last_response)
...     
... 
(4L, datetime.datetime(2013, 5, 16, 15, 25, 40))
(2L, datetime.datetime(2013, 5, 16, 15, 16, 46))
(1L, None)
(3L, None)
(6L, None)
(7L, None)
(8L, None)
(9L, None)
>>> 
Другие вопросы по тегам