
在 Django 项目中通过 requests 调用外部 API 时,含法语等重音字符(如 é、è)的文本因手动拼接 JSON 字符串导致编码错误,实际发送为 Latin-1 编码的 \xc3\xa9,而非标准 UTF-8;正确做法是使用 json= 参数或显式 .encode('utf-8')。
在 django 项目中通过 requests 调用外部 api 时,含法语等重音字符(如 é、è)的文本因手动拼接 json 字符串导致编码错误,实际发送为 latin-1 编码的 `\xc3\xa9`,而非标准 utf-8;正确做法是使用 `json=` 参数或显式 `.encode('utf-8')`。
问题根源在于:手动字符串格式化 JSON 是高危操作——不仅易引入语法错误(如引号嵌套、特殊字符转义失败),更关键的是绕过了 JSON 序列化的标准化编码流程。在您的 get_payload() 方法中:
def get_payload(self) -> str:
payload = f"""{{ "accountreference": '{self.account_reference}',
"messages": {self.construct_messages()},
"from": '{self.sender_sms_senderId}',
"characterset": "Unicode",
}}"""
return payload该方法返回的是一个 Python str,当传入 requests.post(data=payload) 时,requests 默认以 latin-1 编码将其转为字节(官方行为),而非 JSON 规范强制要求的 UTF-8。这就是为什么 é 变成 \xc3\xa9(UTF-8 编码)后又被误当作 Latin-1 解析,最终 API 收到乱码。
✅ 推荐解决方案:使用 json= 参数(最简洁、最安全)requests.post(json=...) 会自动:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 调用
json.dumps(..., ensure_ascii=False)(保留原始 Unicode 字符); - 指定
Content-Type: application/json; charset=utf-8; - 以 UTF-8 编码生成字节流并发送。
修改 send() 方法如下:
def send(self) -> requests.Response:
self.login()
payload = {
"accountreference": self.account_reference,
"messages": self.construct_messages(),
"from": self.sender_sms_senderId,
"characterset": "Unicode"
}
return requests.post(
url=f"{BASEURL}v1.0/messagedispatcher",
headers={
"Authorization": f"Basic {self.session_key}",
"Accept": "application/json"
# ⚠️ 移除手动设置的 "Content-type" 和 "charset"
},
json=payload # ← 关键:让 requests 自动处理编码与头信息
)❌ 不推荐方案:手动 encode + data=
若必须使用 data=(例如需自定义序列化逻辑),务必显式编码,并移除冲突的 charset 头:
# 仅当有特殊需求时使用
payload_str = json.dumps({
"accountreference": self.account_reference,
"messages": self.construct_messages(),
"from": self.sender_sms_senderId,
"characterset": "Unicode"
}, ensure_ascii=False) # 确保 é 不被转义为 \u00e9
return requests.post(
url=...,
headers={
"Authorization": f"Basic {self.session_key}",
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8" # 显式声明
},
data=payload_str.encode('utf-8') # 强制 UTF-8 编码
)? 额外注意事项:
- 删除
get_send_headers()中"charset": "utf-8"—— 这不是标准 HTTP 头,且与Content-Type冲突; -
DEFAULT_CHARSET在 Django 2.0+ 才生效,Django 1.11 下默认即utf-8,无需额外配置; -
# coding: utf-8和from __future__ import unicode_literals在 Python 3.6+ 中已无实际作用,可移除; - 环境变量
LANG=C.UTF-8已满足要求,无需修改。
遵循以上实践,即可确保所有 Unicode 字符(包括 é、ñ、中文、emoji)以标准 UTF-8 编码准确送达 API,彻底规避手动拼接 JSON 带来的编码陷阱。

















