Показывать в шаблоне Django только значения not None

У меня есть Model с многочисленными атрибутами; в шаблоне, отображаемом моим DetailView, я хочу показать только те атрибуты, которые не являются None.

Это можно легко сделать с помощью тега шаблона if, который проверяет, не является ли значение атрибута None, но я должен добавить условие if для каждого атрибута в моей модели, а их очень много.

Я хотел бы перебрать все атрибуты и if not None отобразить их. В псевдокоде это будет выглядеть следующим образом:

{% for attribute in my_instance.all_attributes %}
  {% if attribute.value is not None %}
    {{attribute.value}}

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

cls._meta.concrete_fields

или

self._meta.concrete_fields

Теперь, когда у меня есть my_instance.all_attributes в моем примере псевдокода, я могу его итерировать, но я не знаю, как получить фактическое значение атрибута экземпляра.

Авторы Django сделали все возможное, чтобы убедиться, что язык шаблонов не используется для подобных вещей! Насколько я понимаю, они считают, что шаблоны должны заниматься форматированием, а Python - логикой программы.

Есть два способа обойти это. Первый - создать структуру, по которой шаблон может выполнять итерации, и передать ее в контекст DetailView. Что-то вроде

def get_context_data(self):
    data = super().get_context_data(**kwargs)

    fieldnames = [
        x.name for x in self.object._meta.concrete_fields ]
    display_fields = [
        (name, getattr( self.object, name, None)) for name in fieldnames ]
    display_fields = [ x for x in display_fields if x[1] is not None ]

    data['display_fields'] = display_fields
    return data

и в шаблоне теперь можно сделать

{% for name,value in display_fields %} 

Вы можете предпочесть кодировать список имен вместо использования ._meta.concrete_fields, потому что это позволит вам выбрать порядок их появления. Или вы можете начать с упорядоченного списка и добавить все, что есть в _meta, но еще не в вашем списке (и удалить все, что есть в вашем списке, но не в _meta)

Другой способ - использовать Jinja в качестве шаблонизатора для этого представления.

Вернуться на верх