Contexto
Para un sistema de referidos necesitaba generar QR codes dinamicos por fraccionamiento -- cada uno con una URL unica. Guardar archivos PNG en disco introduce problemas: limpieza, nombres unicos, permisos de directorio, y en hosting serverless simplemente no hay filesystem persistente.
Lo que aprendi
La libreria qrcode de Python puede renderizar a un buffer en memoria con BytesIO. Desde ahi, se convierte a base64 y se retorna como data URI que el browser renderiza directo en un <img>.
Generacion en memoria
import qrcode
import io
import base64
def generate_qr_code(text, size=10):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=size,
border=4
)
qr.add_data(text)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buffer = io.BytesIO()
img.save(buffer, format='PNG')
buffer.seek(0)
img_base64 = base64.b64encode(buffer.getvalue()).decode()
return f"data:image/png;base64,{img_base64}"
Uso en el template
<img src="{{ qr_image }}" alt="QR de referido" />
El valor de qr_image es algo como data:image/png;base64,iVBORw0KGgo... -- el browser lo interpreta como imagen inline sin hacer ninguna peticion HTTP adicional.
Por que este pattern funciona bien
- Cero file storage: no hay archivos temporales que limpiar
- Sin endpoints adicionales: no necesitas una ruta
/static/qr/xxx.png - Cache-friendly: el data URI viaja con el HTML, asi que si cacheas la pagina cacheas el QR
- Compatible con serverless: funciona igual en Lambda, Cloud Run, o un VPS con Gunicorn
Cuando NO usarlo
Si generas QR codes muy grandes (version alta, mucha data) o muchos en una sola pagina, el HTML se infla. En ese caso conviene guardar en Blob storage y servir via CDN. Para un sistema de referidos con 1-3 QR por pagina, el data URI es la solucion mas simple.