Python лямбда в мезонине утилит
Я не могу обернуть голову вокруг этой лямбда-функции (сделать). Это из утилиты Mezzanine:
def send_mail_template(subject, template, addr_from, addr_to, context=None,
attachments=None, fail_silently=None, addr_bcc=None,
headers=None):
"""
Send email rendering text and html versions for the specified
template name using the context dictionary passed in.
EDITED FOR SIMPLICITY
"""
context.update(context_settings())
# Loads a template passing in vars as context.
render = lambda type: loader.get_template("%s.%s" %
(template, type)).render(Context(context))
# Create and send email.
msg = EmailMultiAlternatives(subject, render("txt"),
addr_from, addr_to, addr_bcc,
headers=headers)
msg.attach_alternative(render("html"), "text/html")
msg.send(fail_silently=fail_silently)
Я пытаюсь передать список шаблонов в мою собственную версию функции. поэтому параметр "шаблон", представляющий собой строку пути к шаблону, становится списком (шаблонами) строк путей. Затем мне нужно перебрать список и применить все, что происходит в лямбде, а затем вызвать.render(Context(context)) для него.
это самый уродливый код, но он показывает, что мне нужно в качестве конечного результата:
render = lambda type: loader.get_template("%s.%s" %
(templates[0], type))
render2 = lambda type: loader.get_template("%s.%s" %
(templates[1], type))
# Create and send email.
msg = EmailMultiAlternatives(subject,(render("txt")+render2('txt')).render(Context(context)),
addr_from, addr_to, addr_bcc,
headers=headers)
msg.attach_alternative((render("html")+render2('html').render(Context(context)), "text/html")
msg.send(fail_silently=fail_silently)
Вышеописанное работает, но, очевидно, просто отвратительно, и список будет неизвестной длины.
Пожалуйста! Кто-нибудь может де-конструировать лямбда-функцию?
Answer with help from Arthur Tacca
Я пытаюсь создать тело электронной почты, объединяя шаблоны вместе, поэтому мне нужно передать список шаблонов, которые будут отображаться как текстовые и html тела вместе. вот что работает:
def render_templates(types,templates,context):
template_body = ''
for template in templates:
template_body += loader.get_template("%s.%s" % (template, types)).render(Context(context))
return template_body
def send_mail_template(subject, templates, addr_from, addr_to, context=None,
attachments=None, fail_silently=None, addr_bcc=None,
headers=None):
"""
...
"""
context.update(context_settings())
msg = EmailMultiAlternatives(subject, render_templates("txt",templates,context),
addr_from, to, [],
headers)
msg.attach_alternative(render_templates("html",templates,context), "text/html")
msg.send(fail_silently=fail_silently)
1 ответ
Я не понимаю, почему вы используете функцию / лямбда вообще, а не просто (для первого примера):
rendered = loader.get_template("%s.%s" % (template, "txt")).render(Context(context))
Я предполагаю, что это упрощение работает только потому, что вы упростили контекст, в котором вы делаете это; возможно, в реальном коде вам нужно передать функцию рендеринга куда-нибудь, чтобы вызвать ее позже. Если нет, вы можете полностью избавиться от лямбд.
Вот небольшой момент, но он может немного прояснить ситуацию: нет абсолютно никакой разницы между
render = lambda type: loader.get_template("%s.%s" %
(templates[0], type))
render2 = lambda type: loader.get_template("%s.%s" %
(templates[1], type))
а также:
def render(type):
return loader.get_template("%s.%s" % (templates[0], type))
def render2(type):
return loader.get_template("%s.%s" % (templates[1], type))
(Хорошо, одно небольшое отличие состоит в том, что вы получаете более четкую трассировку стека, если есть исключение.) На самом деле вторая форма - лучший стиль (AKA "более Pythonic"); единственная причина использовать лямбду - если функция настолько коротка, что ее передают другой функции, даже не присваивая ее переменной.
В вашем случае это означает, что вы можете использовать итерацию, если вам нравится:
def render_all(types):
result_list = []
for type, template in zip(types, templates):
result_list.append(loader.get_template("%s.%s" % (template, type)))
return "".join(result_list)
Это созрели для понимания списка / генератора:
def render_all(types):
return "".join(loader.get_template("%s.%s" % (template, type))
for type, template in zip(types, templates))