You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中编写支持变量列表的HTML邮件发送函数

问题原因&解决方案

错误原因

你遇到的报错是因为str.format()的用法完全错误,同时你的实现逻辑绕开了Django模板渲染的原生能力,属于多此一举:

  • 字符串是不可变类型,你在循环中执行html_message.format(variable)不会修改原变量,返回的新字符串没有被接收赋值
  • 如果你HTML模板中写了{0}、{1}这类占位符,format需要一次性传入所有占位符对应的参数,你循环每次只传1个参数,自然会出现索引超出范围的报错
  • 你调用render_to_string的时候只传入了固定的{'context': 'values'},没有把你实际需要的变量传入模板渲染,额外用format属于完全不必要的操作。

最优实现方案(推荐)

直接用Django模板引擎的原生渲染能力,传入变量字典渲染模板,不需要额外的格式化步骤,变量可读性和可维护性更高:

第一步:修改发送函数

from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.core.mail import get_connection
from django.utils.html import strip_tags
from otr import settings


def send_email(subject, email_template, recipient, username, password, context):
    # 直接把变量字典传入render_to_string完成模板渲染
    html_message = render_to_string(email_template, context)
    plain_message = strip_tags(html_message)

    with get_connection(
            host=settings.EMAIL_HOST,
            port=settings.EMAIL_PORT,
            username=username,
            password=password,
            use_tls=True
    ) as connection:
        send_mail(subject, plain_message, 'Me', [recipient], fail_silently=False,
                  html_message=html_message, connection=connection)

第二步:调整模板写法

你的HTML邮件模板(比如emails/followup_email.html)直接用Django模板语法写变量即可,示例:

<p>尊敬的{{ customer_name }}:</p>
<p>您好!我是{{ dear_user }}</p>
<p>我的联系电话是{{ phone_number }}</p>
<p>此致</p>
<p>{{ sincerely_user }}</p>

第三步:调用方式调整

调用时把变量组装成字典传入即可:

subject = "My subject"
email_template = "emails/followup_email.html"
recipient = queryset.customer_email
username = username_variable
password = password_variable
# 直接组装变量字典
context = {
    "customer_name": "Bob",
    "dear_user": "my_name",
    "phone_number": "1111111111",
    "sincerely_user": "my_name"
}

send_email(subject, email_template, recipient, username, password, context)

兼容原有列表传参的方案(不推荐)

如果你一定要保留原有传变量列表的写法,也可以修改渲染逻辑,不要循环调用format,一次性解包列表传入即可:

def send_email(subject, email_template, recipient, username, password, variable_list):
    html_message = render_to_string(email_template, {})
    # 一次性解包所有变量传入format,接收返回的新字符串
    html_message = html_message.format(*variable_list)
    plain_message = strip_tags(html_message)

    with get_connection(
            host=settings.EMAIL_HOST,
            port=settings.EMAIL_PORT,
            username=username,
            password=password,
            use_tls=True
    ) as connection:
        send_mail(subject, plain_message, 'Me', [recipient], fail_silently=False,
                  html_message=html_message, connection=connection)

注意这种写法需要你模板中的{0}、{1}这类占位符的数量和顺序,和variable_list的长度、顺序完全对应,否则会报错或渲染错误。

内容的提问来源于stack exchange,提问作者Thomas166

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 05:27:01