2012-06-27 2 views
3

У меня есть модель Read, что связано с моделью Article. Я хотел бы сделать запрос, когда статьи уникальны и упорядочены по date_added. Поскольку я использую postgres, я бы предпочел использовать метод .distinct() и указать поле article. Нравится так:Django .order_by() с .distinct() using postgres

articles = Read.objects.order_by('article', 'date_added').distinct('article') 

Однако это не дает желаемого эффекта и заказывает запрос по порядку, в котором они были созданы. Я знаю примечание о .distinct() и .order_by() в документации Django, но я не вижу, что это применимо здесь, поскольку побочный эффект, о котором он упоминает, будет дублировать, и я этого не вижу.

# To actually sort by date added I end up doing this 
articles = sorted(articles, key=lambda x: x.date_added, reverse=True) 

Это выполняет весь запрос, прежде чем я на самом деле это нужно и потенциально может получить очень медленно, если есть много записей. Я уже оптимизировал использование select_related().

Есть ли лучший, более эффективный способ создания запроса с уникальностью связанной модели и даты order_by?

ОБНОВЛЕНИЕ Выход в идеале быть QuerySet прочитанных случаях, когда их связанные статьи является уникальным в QuerySet и только с использованием ОРМ Django (т.е. сортировки в Python).

+0

Какую версию Django вы используете? Передача параметров в 'distinct' доступна только в 1.4+ –

+0

1.4 и с использованием postgres, она работает – ender

ответ

2

Есть ли лучший, более эффективный способ создания запроса с уникальностью родственной модели и order_by date?

Положительно. Трудно сказать без полной картины, но я полагаю, что вы используете Read, чтобы отслеживать, какие статьи есть и не были прочитаны, и, вероятно, привязав это к экземпляру User, чтобы определить, читал ли какой-либо конкретный пользователь статью или нет. Если это так, ваш подход ошибочен. Вместо этого, вы должны сделать что-то вроде:

class Article(models.Model): 
    ... 
    read_by = models.ManyToManyField(User, related_name='read_articles') 

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

user_instance.read_articles.order_by('date_added') 

Это требует необходимости использования distinct из уравнения, так как теперь не будет дубликатов.

UPDATE

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

Article.objects.filter(read_by__isnull=False) 

Или, если вы хотите установить порог популярности, вы можете использовать аннотации:

from django.db.models import Count 

Article.objects.annotate(read_count=Count('read_by')).filter(read_count__gte=10) 

которая предоставит вам только те статьи, которые читают не менее 10 пользователей.

+0

Спасибо за вашу помощь! Этот конкретный запрос на самом деле соответствует тому, что читают несколько пользователей, которых вы читаете. Я оставил другой фильтр, который делает это.Мне нужно это для агрегирования для нескольких пользователей, поэтому в этом случае более эффективно запрашивать модель Read, а не модель Article. Имеет ли это смысл? – ender

+0

См. Обновление выше. –

+0

@ChrisPratt у вас есть опечатка в первом запросе вашего обновления: ready_by –

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