使用 Django 打印 PDF 格式的条形码



我在django中使用render_to_string来解析HTML并导出为PDF。

html = render_to_string("etiquetaTNT.html", {
'context': context,
'barcode': b,
'barcodeimg': barcodeimg,
})
font_config = FontConfiguration()
HTML(string=html).write_pdf(response, font_config=font_config)
return response

我正在尝试在 PDF 中插入条形码。我在 PNG 中生成此条形码。

br = barcode.get('code128', b, writer=ImageWriter())
filename = br.save(b)
barcodeimg = filename

但是模板中的PDF,不显示图像。

<img class="logo" src="{{barcodeimg}}" alt="Barcode" />

我不知道在我想要的模板中保存文件名的方法,也不知道在 PDF 中显示的方法,因为显示任何图像。例如,徽标显示在 HTML 模板中,但不显示在 PDF 中。

<img class="logo" src="{{logo}}" alt="TNT Logo" />

我正在使用的库:

import barcode
from barcode.writer import ImageWriter
from django.http import HttpResponse
from django.template.loader import render_to_string
from weasyprint import HTML
from weasyprint.fonts import FontConfiguration

我不想使用Reportlab,因为我需要呈现HTML,而不是Canvas。

理解问题:

想想加载网页时会发生什么。有加载文档的初始请求,然后发出后续请求以获取图像/其他资产。

当你想使用weasyprint打印一些HTML到PDF时,weasyprint必须获取所有其他图像。查看python-barcode文档,br.save(b)只会返回文件名(将保存在当前的工作目录中(。所以你的html看起来像这样:

<img class="logo" src="some_filename.svg" alt="Barcode" />

它如何获取这将取决于您如何设置weasyprint。您可以查看具有自定义URL提取程序django-weasyprint。但就目前而言,weasyprint 无法获取此文件。

一个解决方案

有几种方法可以解决此问题。但这在很大程度上取决于您如何部署它。例如,heroku(据我所知(没有可以写入的本地文件系统,因此您需要将文件写入 s3 等外部服务,然后将其 url 插入模板,然后weasyprint将能够获取。但是,我认为在这种情况下,我们可能可以使用更简单的解决方案。

更好的(也许(解决方案

看看python-barcode文档,看起来您可以使用 SVG 编写。 这很好,因为我们可以直接将 SVG 插入到 HTML 模板中(并且避免获取任何其他资产(。我会建议如下

from io import BytesIO
from barcode.writer import SVGWriter
# Write the barcode to a binary stream
rv = BytesIO()
code = barcode.get('code128', b, writer=SVGWriter())
code.write(rv)
rv.seek(0)
# get rid of the first bit of boilerplate
rv.readline()
rv.readline()
rv.readline()
rv.readline()
# read the svg tag into a string
svg = rv.read()

现在,您只需将该字符串插入模板即可。只需将其添加到上下文中,然后按如下方式呈现:

{{svg}}

增强 @tim-mccurrach 提供的解决方案,我为它创建了一个模板标签。

/app/templatetags/barcode_tags.py

from django import template
from io import BytesIO
import barcode
register = template.Library()
@register.simple_tag
def barcode_generate(uid):
rv = BytesIO()
# code = barcode.get('code128', b, writer=SVGWriter())
code = barcode.get('code128', uid, 
writer=barcode.writer.SVGWriter())
code.write(rv)
rv.seek(0)
# get rid of the first bit of boilerplate
rv.readline()
rv.readline()
rv.readline()
rv.readline()
# read the svg tag into a string
svg = rv.read()
return svg.decode("utf-8")

然后在模板中.html:

{% load barcode_tags %}
{% barcode_generate object.uid as barcode_svg %}
{{barcode_svg | safe}}

最新更新