使用 Django 打印 PDF 中的条形码
Print Barcode in PDF with Django
我在 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)
只是 return 字面上只是文件名,(它将保存在您当前的工作目录中)。所以你的 html 看起来像这样:
<img class="logo" src="some_filename.svg" alt="Barcode" />
它如何获取这将取决于您如何设置 weasyprint
。您可以查看 django-weasyprint
,它有一个自定义的 URL 提取器。但就目前情况而言,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")
然后在 template.html:
{% load barcode_tags %}
{% barcode_generate object.uid as barcode_svg %}
{{barcode_svg | safe}}
我在 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)
只是 return 字面上只是文件名,(它将保存在您当前的工作目录中)。所以你的 html 看起来像这样:
<img class="logo" src="some_filename.svg" alt="Barcode" />
它如何获取这将取决于您如何设置 weasyprint
。您可以查看 django-weasyprint
,它有一个自定义的 URL 提取器。但就目前情况而言,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")
然后在 template.html:
{% load barcode_tags %}
{% barcode_generate object.uid as barcode_svg %}
{{barcode_svg | safe}}