Получите отдельные объекты django из набора запросов, отсортированные по последним

У меня есть эта модель (неактуальные поля скрыты):

class Blog(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    is_published = models.BooleanField(default=False)
    published_date = models.DateTimeField(null=True, default=None, blank=True)

Я хочу получить только последнее сообщение каждого автора, отсортированное по дате публикации.

Я пробовал следующее, на мой взгляд:

blog_list = Blog.objects.filter(is_published=True).order_by('author', '-published_date').distinct('author')

Что работает, кроме, все записи блога сортируются в порядке авторов, а не по дате публикации.

Следующее действительно помогло бы, переключив порядок, но это вызывает ошибку в django:

blog_list = Blog.objects.filter(is_published=True).order_by('-published_date', 'author').distinct('author')

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


person Megawatt    schedule 04.01.2020    source источник
comment
похоже, что в нем участвуют 2 модели, я видел подобные вопросы, и это не применимо к моему вопросу. Хотя проверю и протестирую.   -  person Megawatt    schedule 04.01.2020
comment
Попробуйте это из django.db.models import Max Blog.objects.filter(pk__in=Blog.objects.order_by('-published_date').values('auther_id').annotate(max_id=Max('pk')).values ('max_id'), is_publish=true)   -  person Gorkhali Khadka    schedule 04.01.2020
comment
@GorkhaliKhadka Похоже, это почти помогает! Я вижу несколько уникальных авторских постов. Однако я сталкиваюсь с такими проблемами, как: отображаются не все авторы, а сообщения в блогах не сортируются по дате публикации.   -  person Megawatt    schedule 04.01.2020
comment
Вы решаете свою проблему или нет?   -  person Gorkhali Khadka    schedule 04.01.2020
comment
@GorkhaliKhadka Спасибо, да, это было решено с ответом, который я опубликовал, но я не могу выбрать лучший ответ в течение двух дней. Я попробую другие решения и посмотрю, сделают ли они это лучше.   -  person Megawatt    schedule 04.01.2020
comment
Я также добавил еще один ответ, вы пробовали это? это отлично работает для меня.   -  person Gorkhali Khadka    schedule 04.01.2020


Ответы (5)


Я смог заставить это работать, используя следующее:

blog_ids = Blog.objects.filter(is_published = True)\
.order_by('author_id', '-published_date')\
.distinct('author_id')\
.values('id', flat=True)

blog_list = Blog.objects.filter(id__in=blog_ids)\
.order_by('-published_date')

Который получает именно то, что я хотел!!!!

Более подробную информацию об этом методе можно найти здесь: https://stackoverflow.com/a/32760239/2990550

person Megawatt    schedule 04.01.2020

Я думаю, вы должны попробовать это:

Blog.objects.filter(is_published=True).order_by('-published_date').order_by('author').distinct('author')

Это даст то, что вы хотите. здесь вы получите все последние блоги авторов.

person Ashish    schedule 04.01.2020
comment
Отличная идея, я действительно думал, что это сработает, но после того, как я попробовал, это просто делает то же самое, что и: blog_list = Blog.objects.filter(is_published=True).order_by('author', '-published_date').distinct( 'автор') - person Megawatt; 04.01.2020
comment
Я использую это и получаю правильные данные: Appointments.objects.all().order_by('-date').order_by('user_id').distinct('user_id') Я не знаю, в чем проблема с вами. - person Ashish; 04.01.2020
comment
Вы уверены, что это не дает того же результата, что и: Appointments.objects.all().order_by('user_id', '-date').distinct('user_id')? Это то, что он делает для меня - person Megawatt; 04.01.2020
comment
Я использую Postgresql, поэтому, возможно, SQL отображается по-другому. - person Megawatt; 04.01.2020
comment
Чувак, я тоже использую PSQL - person Ashish; 04.01.2020
comment
Когда я его использовал, он дал те же результаты, что и Blog.objects.filter(is_published=True).order_by('author', '-published_date').distinct('author') который, как я уже говорил, пробовал и был неверным . - person Megawatt; 04.01.2020

Попробуйте это решение

blog_list = Blog.objects.filter(is_published=True).distinct('author').order_by('-published_date', 'author')
person anjaneyulubatta505    schedule 04.01.2020
comment
не работает, это правильно отсортирует сообщения в блоге, но покажет все сообщения авторов. Мне нужен только последний пост автора. - person Megawatt; 04.01.2020
comment
Я получаю сообщение об ошибке при использовании обновленного ответа, такое же, как ошибка, сгенерированная с использованием второй строки, которую я разместил в вопросе. - person Megawatt; 04.01.2020

Попробуйте этот код. Теперь это удаление нулевых значений.

from django.db.models import Max

Blog.objects.filter(pk__in=Blog.objects.order_by('-published_date').values(
        'author_id').annotate(max_id=Max('pk')).values('max_id'),
                        is_published=True, author_id__isnull=False).order_by('-author_id')
person Gorkhali Khadka    schedule 04.01.2020

Вы можете прочитать этот пост в официальной документации Djang. Согласно этому сообщению, когда вы указываете имена полей в предложении different, вы должны указать order_by() в QuerySet, а поля в order_by() должны начинаться с полей в different() в том же порядке. Чтобы достичь указанной выше цели, выполните следующие действия:

from django.db.models import Max
blog_list = Blog.objects.filter(is_published=True).values('author').annotate(Max('published_date'))
person MohammadMahdi Aghajani    schedule 04.01.2020
comment
Я получаю сообщение об ошибке: объект «QuerySet» не имеет атрибута «group_by» - person Megawatt; 04.01.2020