2015-12-11 3 views
2

У меня есть следующий шаблон HTML в переменном Python:Продвинутое форматирование строки Python с пользовательскими заполнителями?

template = """ 
    <script> 
     function work() 
     { 
      alert('bla'); 
     } 
    </script> 

    Success rate is {value:.2%} percent. 
""" 

Я хочу, чтобы заменить {value:.2%} с некоторым десятичным числом с соответствующим форматированием. Поскольку в моем шаблоне может быть много кода JavaScript, я хочу избежать экранирования фигурных фигурных скобок с {{ и }}, поэтому использование template.format(...) напрямую - это не вариант.

Использование Template(template).substitute(...) также кажется невозможным, потому что я хочу форматировать для value.

Я мог бы заменить {value:.2%} с соответствующим синтаксисом %(value)..., а затем использовать template % .... Но я не являюсь поклонником этого синтаксиса, потому что для большинства переменных в реальном мире шаблон не нуждается в расширенном форматировании, поэтому я хочу, чтобы синтаксис заполнителя был простым.

Так что мой вопрос, можно ли использовать пользовательские заполнители в шаблоне, который позволил бы для расширенного форматирования при необходимости, то есть иметь просто {{value}} или [[value]] но {{value:.2%}} или [[value:.2%]]?

Edit: Наконец, я хочу, чтобы избежать ошибок, которые .format(...) будут производить, когда шаблон содержит заполнители, такие как {{dont_want_this_substituted}}, для которых переданная словарь не содержит значения. То есть, я хочу только заменить только определенные заполнители, а не все, что отображается в шаблоне.

Редактирование 2: Для достижения того, что я хочу, я могу сначала захватить все заполнители с регулярным выражением, затем отформатировать их содержимое и, наконец, сделать замену в шаблоне. Но мне интересно, существует ли более простое решение.

Редакция 3: Было предложено разделить шаблон, чтобы избежать проблем с format(). Однако я хотел бы избежать этого, потому что шаблон фактически исходит из файла.

+0

Невозможно предварительно отформатировать ваши значения? –

+0

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

+0

Почему бы не иметь несколько файлов? Или просто сохраните свои шаблоны отдельно. – leewz

ответ

1

Просто предварительно обработайте шаблон. Например, если вы хотите [[...]] быть ваши маркеры шаблона и оставить одиночные { и } персонажей в одиночку:

template = """ 
    <script> 
     function work() 
     { 
      alert('bla'); 
     } 
    </script> 

    Success rate is [[value:.2%]] percent. 
""" 

result = template.replace("{", "{{").replace("}", "}}").replace("[[", "{").replace("]]", "}").format(value=0.8675309) 

Попытка сделать все это с различным числом фигурных скобок шалунов, так что я бы определенно использовать некоторые другие символы , Однако осторожно, что такие вещи, как [[ и ]], могут иметь место в законном коде JavaScript. Может быть, лучше использовать то, что никогда не могло.

+0

Спасибо, это вариант. Хотя немного сложнее, если я хочу использовать '{{...}}' в качестве заполнителя, то есть, вероятно, потребуется некоторое замещение регулярного выражения. Интересно, есть ли лучший подход? Я также отредактировал оригинальный вопрос с просьбой о замене некоторых заполнителей. –

+0

В этом случае вы захотите написать свой собственный шаблонный движок. – kindall

+1

* ** См. Также: ** http://stackoverflow.com/a/41231617/42223 ;; для решения, которое расширяет метод str.format() с помощью настраиваемого класса. – dreftymac

0

Забудьте регулярное выражение и препроцессинг. Вы должны разбить шаблон так, чтобы переменные части не были в той же строке, что и <script>.

head = """ 
    <script> 
     function work() 
     { 
      alert('bla'); 
     } 
    </script> 
""" 


template = """ 
    {head} 

    Success rate is {value:.2%} percent. 
""" 

Наконец, я хочу, чтобы избежать ошибок, которые .format (...) будет производить, когда шаблон содержит заполнители, такие как {{dont_want_this_substituted}}, для которых переданная словарь не содержит стоимость. То есть, я хочу только заменить только определенные заполнители, а не все, что отображается в шаблоне.

Это может быть Hacky, но вы можете использовать collections.defaultdict, как показано in this answer. Образец кода из этого ответа (изменено).

from collections import defaultdict 

my_csv = '{optional[first]},{optional[middle]},{optional[last]}' 
print(my_csv.format(optional=defaultdict(str, first='John', last='Doe'))) 
+0

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

Смежные вопросы