firstof использование с переменными списка

Я видел, что типы данных списка не сохраняют свою структуру после использования firstof с as. Например:

{% firstof some_list some_string as value %}

Если some_list является допустимым списком выше, он назначается value. Но если я сделаю что-то вроде {% if pk in value %}, произойдет сбой, даже если он преуспеет с {% if pk in some_list %}. Когда я печатаю оба из них:

{{some_list}}
{{value}}

они дают один и тот же результат, но я думаю, что список, вероятно, не сохраняется как список после использования firstof с as. Мысли?


person Anupam    schedule 18.10.2017    source источник


Ответы (2)


Назначение some_list на value работает не так, как вы ожидаете. Результирующий value имеет тип SafeText, а не list. Это можно проверить, используя этот ответ, который добавляет пользовательский тег шаблона get_type для получения типа переменной.

{% firstof some_list as value %}
{{ some_list|get_type }}
{{ value|get_type }}

Что показывает следующее:

<class 'list'>
<class 'django.utils.safestring.SafeText'>

Глядя на документацию поближе, говорится, что firstof :

Выводит первую переменную-аргумент, которая не равна False.

На их примере показано, что {% firstof some_list some_string %} становится:

{% if some_list %}
    {{ some_list }}
{% elif some_string %}
    {{ some_string }}
{% endif %}

Это объясняет, почему value относится к типу SafeText. Присваивание просто присваивает это переменной value. Мне это не кажется ошибкой.

person ikkuh    schedule 18.10.2017
comment
Спасибо за объяснение. Вы знаете, является ли это предполагаемым поведением или ошибкой? - person Anupam; 18.10.2017
comment
Хм, не совсем уверен. Если он присваивает вывод переменной, переменная должна иметь тип присваиваемого значения (иначе назначение не будет иметь большого смысла)? - person Anupam; 18.10.2017
comment
Да, это ожидаемое поведение, если бы это было назначение переменной по умолчанию. Однако разработчики Django решили, что поведение firstof заключается в выводе первой переменной, что приводит к изменению типа на SafeText. Почему это было выбрано, не имеет значения, но результат показывает, что вы не можете ожидать, что тип останется прежним. Так что да, назначение не очень полезно в вашем случае использования. - person ikkuh; 18.10.2017

Мне также понадобилась эта функция, чтобы получить первый нулевой элемент (включая списки) из нескольких и назначить его переменной, поэтому я создал простой тег

@register.simple_tag
def firstofany(*args_list):
    i = 0
    for arg in args_list:
        if arg or i == len(args_list)-1:
            return arg
        else:
            pass

затем в шаблоне просто используйте

{% firstof some_list some_string as value %}

or

{% firstofany some_list some_string last_as_default as value %}

Я надеюсь, что это помогает

person Irugoy    schedule 06.11.2018