django fiber 本身不处理二维码生成,必须自己集成 qrcode + pillow 手动合成 logo;qrcode.make() 返回“1”或“l”模式图像,无透明通道,无法直接叠加 rgba logo,易报 valueerror 或静默丢弃 alpha 通道。

直接说结论:Django Fiber 本身不处理二维码生成,必须自己集成 qrcode + PIL(或 Pillow),再手动合成 Logo;Fiber 只负责把最终图片存进 CMS 媒体库并渲染到页面。
为什么不能直接用 qrcode.make() 加 Logo?
qrcode.make() 返回的是纯色背景的 PIL.Image 对象,不支持透明通道叠加;Logo 合成必须用底层的 qrcode.QRCode 实例 + 手动构建图像,否则 Logo 会被裁掉或失真。
- 常见错误现象:
img = qrcode.make(...)后调用img.paste(logo, pos, logo)报ValueError: bad transparency mask - 根本原因:默认生成的图像是
"1"或"L"模式(无 alpha),而 PNG Logo 通常是"RGBA"模式 - 正确路径:必须用
qrcode.QRCode+qr.make_image(fill_color=..., back_color=...),且指定image_factory=qrcode.image.pil.PilImage
合成 Logo 的关键三步(含尺寸适配)
Logo 不是随便贴上去的——太大遮码、太小看不清、位置偏移导致扫码失败。推荐按 QR 码模块数(module count)动态缩放:
- 先获取 QR 码原始尺寸:
qr = qrcode.QRCode(...); qr.add_data(...); qr.make(); img = qr.make_image(...),此时img.size[0]是像素宽,但更可靠的是用qr.modules_count - Logo 宽高建议设为
qr.modules_count // 5到// 4之间(例如模块数 29 → Logo 取 6–7 px 单位,再乘以缩放因子) - 粘贴位置计算必须基于中心对齐:
pos = ((img.size[0] - logo.size[0]) // 2, (img.size[1] - logo.size[1]) // 2),且logo.convert("RGBA")后再 paste - 务必检查 Logo 是否有透明通道:
logo.mode in ("RGBA", "LA"),否则强制转:logo = logo.convert("RGBA")
如何让 Django Fiber 管理生成的带 Logo 二维码?
Fiber 的 FilerImageField 或媒体上传接口只认文件对象,不能直接传 PIL.Image。必须写入内存文件再交由 Fiber 处理:
- 用
io.BytesIO()接收img.save(fp, format="PNG"),然后重置指针:fp.seek(0) - 构造
Django.core.files.base.ContentFile包裹二进制流:ContentFile(fp.getvalue(), name="qrcode-with-logo.png") - 最后赋值给 Fiber 模型字段(如
page.qr_image),再.save()—— 注意不要漏掉commit=False阶段对文件名/路径的干预 - 避坑点:Fiber 默认媒体根路径可能不含
qrcodes/子目录,需提前在MEDIA_ROOT下建好,或用自定义 upload_to 函数控制
真正容易被忽略的是容错边界:Logo 尺寸超过模块数 20% 就大概率影响扫码率;PIL 图像模式不匹配比报错更危险——它会静默丢弃 alpha 通道,导致白底 Logo 在深色页面上“消失”。动手前先用最小模块数(error_correction=qrcode.constants.ERROR_CORRECT_L)测一遍合成效果。











