Отображение подмножества фиксированной длины списка в шаблоне Django - PullRequest
1 голос
/ 23 июня 2019

Я хотел бы отобразить подмножество фиксированной длины набора связанных объектов в шаблоне Django. Например, представьте, что у меня есть автомобиль, с которым связан объект Owner. Я хотел бы отобразить три самых последних владельца, но также всегда отображать три записи, даже если их меньше. Так

Ford Fiesta AA11 1AA
    1. John Smith
    2. Jane Smith
    3. Jenny Smith

Aston Martin DB9
    1. Richard Rich
    2.
    3.

, даже если у Fiesta было 10 владельцев (а у DB9 был только один).

Наивный способ сделать это будет

<h1>{{car.name}}</h1>
<ol>
  {% for owner in car.owner_set|slice:":3" %}
  <li>{{owner.name}}</li>
  {% endfor %}
</ol>

, но при этом отображается только один элемент списка, если был только один владелец.

Я мог бы также добавить такие строки, как

{% if car.owner_set|length < 2 %}<li></li>{% endif %}
{% if car.owner_set|length < 3 %}<li></li>{% endif %}

но это ужасно. Есть ли лучший способ сделать это?

Ответы [ 3 ]

3 голосов
/ 23 июня 2019

Мне кажется, что проще всего определить новый фильтр.

Создайте пакет templatetags в соответствующем приложении и добавьте файл с именем liststuff.py (или любое другое имя) с помощьюследующий код:

from django import template

register = template.Library()


@register.filter
def exactlength(listlike_thing, desired_length):
    list_thing = list(listlike_thing)
    if len(list_thing) < desired_length:
        # pad the list with as many empty strings as needed
        list_thing += ([''] * (desired_length - len(list_thing)))
    return list_thing[:desired_length]

Затем, в верхней части шаблона, загрузите этот файл (если вы назвали свой файл чем-то другим, измените эту строку соответствующим образом):

{% load liststuff %}

и винициализация вашего цикла, передайте значения через фильтр:

{% for owner in car.owner_set|exactlength:3 %}
2 голосов
/ 23 июня 2019

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

<h1>{{car.name}}</h1>
<ol>
  <li>{{car.owner_set.0.name}}</li>
  <li>{{car.owner_set.1.name}}</li>
  <li>{{car.owner_set.2.name}}</li>
</ol>
2 голосов
/ 23 июня 2019

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

def three_latest_owners(self):
    num = 3
    latest = list(self.owner_set.all()[:num])
    latest += [None] * num
    return latest[:num]

Тогда в шаблоне {% for owner in car.three_latest_owners %}

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