Шаблон Django Slice-Порядок Реверса

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

{% for comment in thread.comment_set.all|slice:":3" %}

теперь я хотел бы получить последние 3 результата моих комментариев, поэтому я решил, что простой": -3 "или" -3 " сделает трюк, увы:

Caught an exception while rendering: Negative indexing is not supported.

продукты:

{% for comment in thread.comment_set.all|slice:":3" reversed %}

не делает трюк, потому что если у меня есть 5 комментариев, вместо 1,2,3 он отображает первые три в 3,2,1 порядок.

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

решение

{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" %}

отображает последние три благодаря моей таблице с созданной меткой времени.

6 ответов


запросы базы данных Django оцениваются лениво, поэтому результат thread.comment_set.all - Это QuerySet, а не список. QuerySet поддерживает множество функций, подобных списку, но не отрицательное срезание, поэтому ошибка индексирования не исходит из самого фильтра шаблона. (Если вам интересно, срезы на объектах QuerySet переводятся в limit предложение в инструкции SQL, поэтому вы не можете использовать отрицательное число).

в общем, Django поощряет строгую развязку шаблонов и моделей; the views.py модуль-это клей, в котором вы выполняете любую работу, требующую знания моделей баз данных и методов queryset для преобразования данных модели в простые переменные и структуры для шаблона.

выполнение связанного запроса на модели из шаблона-это не то, что вы обычно видите в шаблоне Django, и для этого есть веская причина. Прямо сейчас может показаться очень простым срезать последние три элемента из comment_set. Однако имейте в виду, что база данных будет не возвращайте результаты в любом гарантированном порядке. Это означает, что в дополнение к вашему срезу вам также нужно добавить предложение order_by; просто нет способа выразить это в шаблоне, и не должно быть. Лучше думать о представлении как о переводе между вашей моделью и шаблоном, и пусть такая работа с базой данных выполняется там, а не встроена в HTML.

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

# take first three sorted descending
comments = thread.comment_set.order_by('-something')[:3]

context = Context({'comments':comments})
return HttpResponse(tmplt.render(context))

если вы должны сделать нарезку в шаблоне, и вы действительно не заботитесь о сортировке результатов, передайте список шаблону. The slice фильтр с радостью сделает отрицательную нарезку:

comments = list(thread.comment_set.all())
context = Context('comments':comments)

в шаблоне:

{% for comment in comments|slice:"-3:" %}

Я не видел слишком часто используемый фильтр dictsortreversed, и, согласно документам, для сортировки по

{% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %}

используйте атрибут "ordering" мета-класса класса Comment для установки требуемого порядка элементов.

шаблоны IMO не являются подходящим местом для заказа вашего набора данных. Заказ должен производиться либо в моделях, либо в представлениях.


Мне нужно было только это и сделал более полное решение, я думаю. Надеюсь, люди найдут это полезным. Представление должно найти идентификатор последняя вставленная запись (пример здесь). Вы должны изменить порядок и получить идентификатор (PK) новейшей последней введенной записи, которая теперь будет первой записью, легко найти в верхней части кучи ;-). Вычислите желаемое значение идентификатора нижнего предела, затем отсортируйте его от Нижнего к последнему или последнему значению с помощью этого оператора в конце ...[n:m] (I подумайте, что это всего лишь оператор списка), отбрасывая нежелательные записи, а затем представляйте их в обычном порядке. Для примера таблиц django вот мой код:

def showLatestRels(request):
    #This view shows the latest 15 entries in the Release table
    LastInserted = Release.objects.order_by('-pk')[0]
    UpperLimit = LastInserted.id
    LowerLimit = UpperLimit - 15
    RelTable = Release.objects.all()
    tablevalslat = ReleaseTable(RelTable[LowerLimit:UpperLimit])
    RequestConfig(request).configure(tablevalslat)
    return render(request, 'DCESrtap/latrels.html', {'tablevalslat': tablevalslat}

)

множество способов сделать это, см. Django docs делает / ограничивает запросы
Но идея диктсорта не сработала....


не можете ли вы просто нарезать список, прежде чем передавать его в свой шаблон?


вы можете отменить набор запросов, если он уже заказан "создан". Итак, вот более быстрое решение.

{% for comment in thread.comment_set.all.reverse|slice:":3" %}

кроме того, если вы не хотите в обратном порядке.

{% for comment in thread.comment_set.all.reverse|slice:":3"|dictsort:"created" %}

хотя вы должны следовать совету Jarrets Hardie выше и делать всю эту логику в представлениях, а не в шаблонах.