Django: Как выбрать ограниченное количество строк для каждого внешнего ключа? - PullRequest
5 голосов
/ 15 июля 2011
class Comment (models.Model):
        user = models.ForeignKey(User, related_name="comments")
        title = models.TextField(max_length=256)
        comment = models.TextField(max_length=1286)
        created = models.DateTimeField(db_index=True)

Теперь, как мне получить последние комментарии, но ограничить результаты только (скажем, 3) комментариями для одного и того же пользователя?

Вот как это делается в чистом SQL: Как выбрать ограниченное количество строк для каждого внешнего ключа?

1 Ответ

3 голосов
/ 15 июля 2011

Полагаю, это будет работать:

Comment.objects.filter(*[
    ~Q(id__in=user.comments.order_by('-created')[3:].values_list('id', flat=True))
    for user in User.objects.all()
])

Тем не менее, это не кажется ни питонским, ни эффективным способом решения проблемы. (Проблема эффективности может быть несколько решена с помощью кэша, но все же.)

Чего ты пытаешься достичь? Вы можете просто получить все комментарии пользователей и использовать только последние три. Предполагая, что ваши комментарии упорядочены по полю -created:

{% for user in users %}
    {% for comment in user.comments.all|slice:"3" %}{{ comment }}{% endfor %}
{% endfor %}

Срез будет преобразован в предложение LIMIT в SQL-запросе, поэтому вы все равно не получите все комментарии. Конечно, для получения всех комментариев будет выполнено более одного запроса, поэтому использование кэширования шаблонов может помочь.

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

Необработанный SQL

Если вы знаете, как делать то, что вы хотите, с необработанным SQL ([1] может помочь), то вам просто нужно найти способ как-то вставить его в extra() ([2] пример сложного дополнительного запроса, который может дать вам представление).

[1] Как выбрать ограниченное количество строк для каждого внешнего ключа?

[2] .extra django (где = предложения перекрываются переименованием таблицы .filter (foo__in = ... subselect

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...