Шаблон 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 выше и делать всю эту логику в представлениях, а не в шаблонах.