kozea / flask-weasyprint Goto Github PK
View Code? Open in Web Editor NEWGenerate PDF files out of your Flask website thanks to WeasyPrint
Home Page: https://doc.courtbouillon.org/flask-weasyprint
License: BSD 3-Clause "New" or "Revised" License
Generate PDF files out of your Flask website thanks to WeasyPrint
Home Page: https://doc.courtbouillon.org/flask-weasyprint
License: BSD 3-Clause "New" or "Revised" License
Hi,
Im having issues when attempting to import an image i have tried everything i can find online but i still keep getting the same error:
weasyprint.urls.URLFetchingError: ValueError: Flask-WeasyPrint got HTTP status 404 NOT FOUND for https://performance.pythonanywhere.comb'/static/graphs/pi_graph.png'
I have simplified the code right down, still getting the same error:
@reports.route('/print', methods=["POST", "GET"])
@login_required
def print_report():
return render_pdf("https://performance.pythonanywhere.com/static/graphs/pi_graph.png")
Is there a way of creating a custom url_fetcher in order to rectify this issue? ( i cannot find any documentation online on how to create a custom url_fetcher so i havent even tried). I tried altering it to url_for that gave the same error as well.
I'm using weasyprint version 53.4 and the latest pip installable version of flask-weasyprint. Python 3.9. Here is a minimal working example of the problem:
from flask import url_for
from flask_weasyprint import CSS
url = url_for('static', filename='pdfstyle.css')
css = CSS(url)
The url_fetcher logic seems to be broken in this instance since it generates the following error:
weasyprint.urls.URLFetchingError: ValueError: Flask-WeasyPrint got HTTP status 403 FORBIDDEN for https://127.0.0.1:5000b'/static/pdfstyle.css'
Notice the conversion of the filename to a bytes object....
The example app: http://packages.python.org/Flask-WeasyPrint/#an-example-app gives the following example:
@app.route('/hello_<name>.pdf')
def hello_pdf(name):
# Make a PDF from another view
return render_pdf(url_for('hello_html', name=name))
which can be problematic because render_pdf doesn't pass the cookies when sending the request through wsgi. I believe that a important use case is private documents only accessible when authenticated, hence cookies.
It could easily be replaced with those two examples:
@app.route('/hello_<name>.pdf')
def hello_pdf(name):
# Make a PDF from another view
html = hello_html(name)
return render_pdf(HTML(string=html))
# and
@app.route('/external.pdf')
def external_pdf():
# Make a PDF from another domain
return render_pdf("http://some_other_url.tld/path/to/stuff")
Hi,
Backstory: I recently ran into some issues with weasyprint. However as weasy does not actually write any logs by default (no handler on the logger), this took quite some time to debug, until I figured out how to enable at least rudimentary logging. I.e. quite literally threw in this code before the render_pdf...
import logging
logger = logging.getLogger('weasyprint')
logger.addHandler(logging.FileHandler('/tmp/weasyprint.log'))`
Request: I think it would be really neat if flask-weasyprint would forward the weasyprint logs to flask, so they get handled by the app.logger. Sadly I got no idea how to do that or I'd include a patch :/
Cheers :)
Hello, i'm using flask-weasyprint on my local enviroment in Ubuntu, to generate pdf files with some images in differents formats and works fine.
But when i made deploy on development server on CentOS 6.9 i got the next error related with gdk-pixbuf2
symbol 'gdk_pixbuf_get_byte_length' not found in library 'libgdk_pixbuf-2.0.so': /usr/lib64/libgdk_pixbuf-2.0.so: undefined symbol: gdk_pixbuf_get_byte_length
Reading about this i found that gdk_pixbuf_get_byte_length is only available for gdk-pixbuf2 since version 2.26 but in CentOS 6.9 is only available until version 2.24.
How can i update this package? Is possible install a newest version of gdk-pixbuf2 on CentOS?
When an SVG file is fetched by Flask-WeasyPrint, if the file has internal references, CairoSVG attempts to retrieve the SVG file again and can fail because this request isn't intercepted by Flask-WeasyPrint.
An example is when a PDF file is converted to SVG using pdftocairo
, it tends to include characters this way:
<symbol overflow="visible" id="glyph0-1">
...
</symbol>
...
<use xlink:href="#glyph0-1" ... "/>
The problem can be reproduced by changing the SVG in the flask_weasyprint/test_app.py
file to include references, e.g.:
'graph.svg': '''
<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
width="1600" height="1000" viewBox="0 0 160 100">
<style>
text { text-anchor: middle; font-size: 10px }
</style>
{% for i, (label, value, color) in series %}
<rect x="{{ 10 + i * 50 }}" y="{{ 75 - value }}"
+ id="{{ label }}"
width="40" height="{{ value }}"
fill="{{ color }}" stroke="#333" rx="5" ry="5" />
+ <use xlink:href="#{{ label }}" />
<text x="{{ 30 + i * 50 }}" y="90">{{ label }}</text>
{% endfor %}
</svg>
Then the test fails:
$ python2 -m flask_weasyprint.tests
..Failed to load image at http://localhost/foo/graph?data=42,27.3,63&labels=Lorem,ipsum,sit : IOError: [Errno socket error] [Errno 111] Connection refused
Failed to load image at http://localhost/foo/graph?data=42,27.3,63&labels=Lorem,ipsum,sit : IOError: [Errno socket error] [Errno 111] Connection refused
Failed to load image at http://localhost/foo/graph?data=42,27.3,63&labels=Lorem,ipsum,sit : IOError: [Errno socket error] [Errno 111] Connection refused
.Failed to load image at http://localhost/foo/graph?data=42,27.3,63&labels=Lorem,ipsum,sit : IOError: [Errno socket error] [Errno 111] Connection refused
F...
======================================================================
FAIL: test_png (__main__.TestFlaskWeasyPrint)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".../Flask-WeasyPrint/flask_weasyprint/tests.py", line 97, in test_png
colors = [get_pixel(x, 320) for x in [180, 280, 380]]
File ".../Flask-WeasyPrint/flask_weasyprint/tests.py", line 94, in get_pixel
assert alpha == 0xff
AssertionError
----------------------------------------------------------------------
Ran 7 tests in 0.466s
FAILED (failures=1)
I think what's happening is that WeasyPrint provides a base_url
to the weasyprint.images.SVGImage.__init__
method (unless it's a "data:" URI). This is then passed to CairoSVG. When CairoSVG tries to render the elements with the internal reference it calls the cairosvg.parser.Tree.__init__
method. This does:
url, element_id = url.split("#", 1)
(So url
is empty for the internal reference.) Since there is a parent URL the url
gets set to it:
url = parent.url
and it fails at the urlopen
call:
Traceback (most recent call last):
File ".../WeasyPrint-0.26/weasyprint/images.py", line 111, in __init__
svg = self._render()
File ".../WeasyPrint-0.26/weasyprint/images.py", line 138, in _render
output=None, dpi=96)
File ".../cairosvg/surface/__init__.py", line 160, in __init__
self.draw_root(tree)
File ".../cairosvg/surface/__init__.py", line 213, in draw_root
self.draw(node)
File ".../cairosvg/surface/__init__.py", line 384, in draw
self.draw(child)
File ".../cairosvg/surface/__init__.py", line 384, in draw
self.draw(child)
File ".../cairosvg/surface/__init__.py", line 384, in draw
self.draw(child)
File ".../cairosvg/surface/__init__.py", line 327, in draw
TAGS[node.tag](self, node)
File ".../cairosvg/surface/defs.py", line 419, in use
tree = Tree(url=url, parent=node, tree_cache=surface.tree_cache)
File ".../cairosvg/parser.py", line 293, in __init__
input_ = urlopen(url)
...
IOError: [Errno socket error] [Errno 111] Connection refused
Failed to load image at http://localhost/... : IOError: [Errno socket error] [Errno 111] Connection refused
There doesn't seem to be an easy way to fix this from Flask-WeasyPrint. It would be nice if CairoSVG didn't attempt to fetch the image again when it encounters an internal reference. A possible workaround would be to have a way to configure WeasyPrint not to pass the base URL to CairoSVG, which could be used when it is being run from Flask-WeasyPrint. A temporary kludge would be to monkey-patch it so that it gets a "data:" URI for everything, as below. (With this kludge in place, the test works with the edited SVG above.)
from weasyprint.images import SVGImage
old_init = SVGImage.__init__
def new_init(self, svg_data, base_url):
return old_init(self, svg_data, 'data:')
SVGImage.__init__ = new_init
We are using Flask-WeasyPrint==0.6, HTML Content are overlapping.
What will be the reason?
For reference , we are using below font css
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,bold);
@page { margin: 10px 10px 25px 0px; background: white; size: 18in 18in; @bottom-center { font-family: 'Open Sans', 'serif'; content: "Page "counter(page)" / " counter(pages) ; font-size: 20px; color: #53565a; } } body{ font-family: 'Open Sans','serif'; }
The raw Code:
# encoding=utf8
from flask import *
from sailing import app
from sailing.core import core
from sailing.database.training_tasks import db_training_tasks
from sailing.database.training_tasks_images import db_training_tasks_images
from flask_weasyprint import HTML, render_pdf
import sys
reload(sys)
sys.setdefaultencoding('utf8')
@app.route("/training_tasks/<id>.pdf")
def training_tasks_pdf(id):
return render_pdf(url_for('training_tasks', id=id))
@app.route("/training_tasks/", methods=['GET'])
def training_tasks():
if request.args.get('id'):
try:
int(request.args.get('id'))
except:
return redirect("/training_tasks/")
dbdata = db_training_tasks.query.filter(db_training_tasks.id==request.args.get('id')).first()
if not dbdata:
return redirect("/training_tasks/")
templateData = {
"title_suf": dbdata.title,
"id": request.args.get('id'),
"content": dbdata.content
}
templateData.update(core)
dbimages = db_training_tasks_images.query.filter(db_training_tasks_images.id_task==request.args.get('id')).all()
if len(dbimages) != 0:
return render_template("training_tasks.html", dbimages=dbimages, **templateData)
else:
return render_template("training_tasks.html", **templateData)
else:
templateData = {
"title_suf": "Training Tasks"
}
templateData.update(core)
dbdata_all = db_training_tasks.query.all()
return render_template("training_home.html", dbdata=dbdata_all, **templateData)
@app.route("/training_plan/", methods=['GET'])
def training_plan():
templateData = {
"title_suf": "Training Plan"
}
templateData.update(core)
return render_template("training_plan_home.html", **templateData)
The Log:
127.0.0.1 - - [15/Jul/2016 15:55:18] "GET /training_tasks/1.pdf HTTP/1.0" 500 -
Traceback (most recent call last):
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/daniel/sailing.systems/sailing/training.py", line 15, in training_tasks_pdf
return render_pdf(url_for('training_tasks', id=id))
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask_weasyprint/__init__.py", line 208, in render_pdf
html = HTML(html)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask_weasyprint/__init__.py", line 182, in HTML
return _wrapper(weasyprint.HTML, *args, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/flask_weasyprint/__init__.py", line 165, in _wrapper
return class_(guess, *args, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/weasyprint/__init__.py", line 92, in __init__
namespaceHTMLElements=False)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/html5lib/html5parser.py", line 35, in parse
return p.parse(doc, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/html5lib/html5parser.py", line 235, in parse
self._parse(stream, False, None, *args, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/html5lib/html5parser.py", line 85, in _parse
self.tokenizer = _tokenizer.HTMLTokenizer(stream, parser=self, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/html5lib/_tokenizer.py", line 36, in __init__
self.stream = HTMLInputStream(stream, **kwargs)
File "/home/daniel/sailing.systems/venv/lib/python2.7/site-packages/html5lib/_inputstream.py", line 151, in HTMLInputStream
return HTMLBinaryInputStream(source, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'encoding'
Trying to install flask_weasyprint with Python 2.7 and get the following error. Anyway to get Python 2.7 to work with the module?
(venv) C:\api>pip install flask_weasyprint
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting flask_weasyprint Using cached https://files.pythonhosted.org/packages/0f/b5/7292f35a199ea50ac82b06d2a9000a51d16282469f674686fcadc2ae00fb/Flask_WeasyPrint-0.6-py2.py3-none-any.whl Requirement already satisfied: Flask in c:\venv\lib\site-packages (from flask_weasyprint) (1.0.2) Collecting WeasyPrint>=0.12 Using cached https://files.pythonhosted.org/packages/89/05/4eb7b5135bf94465a61b6ddfa6e84526cdc1b15385a3bed7aa86b5bda621/WeasyPrint-44.tar.gz ERROR: Command errored out with exit status 1: command: 'c:\venv\scripts\python.exe' -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'c:\\users\\nathan\\appdata\\local\\temp\\pip-install-wwzlwq\\WeasyPrint\\setup.py'"'"'; __file__='"'"'c:\\users\\nathan\\appdata\\local\\temp\\pip-install-wwzlwq\\WeasyPrint\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base 'c:\users\nathan\appdata\local\temp\pip-install-wwzlwq\WeasyPrint\pip-egg-info' cwd: c:\users\nathan\appdata\local\temp\pip-install-wwzlwq\WeasyPrint\ Complete output (5 lines): Traceback (most recent call last): File "<string>", line 1, in <module> File "c:\users\nathan\appdata\local\temp\pip-install-wwzlwq\WeasyPrint\setup.py", line 20, in <module> 'WeasyPrint does not support Python 2.x anymore. ' RuntimeError: WeasyPrint does not support Python 2.x anymore. Please use Python 3 or install an older version of WeasyPrint. ---------------------------------------- ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
Hello install Flask-WeasyPrint successfully, but when I want to use it sends me an error
Installing Flask-WeasyPrint:
C:\Trabajo\OTROS\FONIDE\NewWebApp>pip install flask_weasyprint Collecting flask_weasyprint Downloading flask_weasyprint-1.0.0-py3-none-any.whl (5.7 kB) Requirement already satisfied: flask>=2.0.0 in c:\program files\python38\lib\site-packages (from flask_weasyprint) (2.2.2) Collecting weasyprint>=43.0 Downloading weasyprint-56.1-py3-none-any.whl (256 kB) ---------------------------------------- 256.8/256.8 kB 3.2 MB/s eta 0:00:00 Requirement already satisfied: itsdangerous>=2.0 in c:\program files\python38\lib\site-packages (from flask>=2.0.0->flask_weasyprint) (2.1.2) Requirement already satisfied: Jinja2>=3.0 in c:\program files\python38\lib\site-packages (from flask>=2.0.0->flask_weasyprint) (3.1.2) Requirement already satisfied: click>=8.0 in c:\program files\python38\lib\site-packages (from flask>=2.0.0->flask_weasyprint) (8.1.3) Requirement already satisfied: Werkzeug>=2.2.2 in c:\program files\python38\lib\site-packages (from flask>=2.0.0->flask_weasyprint) (2.2.2) Requirement already satisfied: importlib-metadata>=3.6.0 in c:\program files\python38\lib\site-packages (from flask>=2.0.0->flask_weasyprint) (4.12.0) Requirement already satisfied: html5lib>=1.1 in c:\program files\python38\lib\site-packages (from weasyprint>=43.0->flask_weasyprint) (1.1) Requirement already satisfied: tinycss2>=1.0.0 in c:\program files\python38\lib\site-packages (from weasyprint>=43.0->flask_weasyprint) (1.1.1) Requirement already satisfied: Pillow>=4.0.0 in c:\program files\python38\lib\site-packages (from weasyprint>=43.0->flask_weasyprint) (9.2.0) Requirement already satisfied: cffi>=0.6 in c:\program files\python38\lib\site-packages (from weasyprint>=43.0->flask_weasyprint) (1.15.1) Collecting Pyphen>=0.9.1 Using cached pyphen-0.13.0-py3-none-any.whl (2.0 MB) Requirement already satisfied: cssselect2>=0.1 in c:\program files\python38\lib\site-packages (from weasyprint>=43.0->flask_weasyprint) (0.7.0) Collecting pydyf>=0.2.0 Downloading pydyf-0.3.0-py3-none-any.whl (6.8 kB) Collecting fonttools[woff]>=4.0.0 Downloading fonttools-4.37.3-py3-none-any.whl (959 kB) ---------------------------------------- 960.0/960.0 kB 10.1 MB/s eta 0:00:00 Requirement already satisfied: pycparser in c:\program files\python38\lib\site-packages (from cffi>=0.6->weasyprint>=43.0->flask_weasyprint) (2.21) Requirement already satisfied: colorama in c:\program files\python38\lib\site-packages (from click>=8.0->flask>=2.0.0->flask_weasyprint) (0.4.5) Requirement already satisfied: webencodings in c:\program files\python38\lib\site-packages (from cssselect2>=0.1->weasyprint>=43.0->flask_weasyprint) (0.5.1) Collecting brotli>=1.0.1 Using cached Brotli-1.0.9-cp38-cp38-win_amd64.whl (365 kB) Collecting zopfli>=0.1.4 Downloading zopfli-0.2.1-cp38-cp38-win_amd64.whl (111 kB) ---------------------------------------- 111.1/111.1 kB 6.3 MB/s eta 0:00:00 Requirement already satisfied: six>=1.9 in c:\program files\python38\lib\site-packages (from html5lib>=1.1->weasyprint>=43.0->flask_weasyprint) (1.16.0) Requirement already satisfied: zipp>=0.5 in c:\program files\python38\lib\site-packages (from importlib-metadata>=3.6.0->flask>=2.0.0->flask_weasyprint) (3.8.1) Requirement already satisfied: MarkupSafe>=2.0 in c:\program files\python38\lib\site-packages (from Jinja2>=3.0->flask>=2.0.0->flask_weasyprint) (2.1.1) Installing collected packages: brotli, zopfli, Pyphen, pydyf, fonttools, weasyprint, flask_weasyprint Successfully installed Pyphen-0.13.0 brotli-1.0.9 flask_weasyprint-1.0.0 fonttools-4.37.3 pydyf-0.3.0 weasyprint-56.1 zopfli-0.2.1
Error sent to me when trying to use it:
Traceback (most recent call last): File "c:\program files\python38\lib\site-packages\flask\app.py", line 2525, in wsgi_app response = self.full_dispatch_request() File "c:\program files\python38\lib\site-packages\flask\app.py", line 1822, in full_dispatch_request rv = self.handle_user_exception(e) File "c:\program files\python38\lib\site-packages\flask\app.py", line 1820, in full_dispatch_request rv = self.dispatch_request() File "c:\program files\python38\lib\site-packages\flask\app.py", line 1796, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "C:\Trabajo\OTROS\FONIDE\NewWebApp\app\profile\routes.py", line 1365, in cedula_ide from flask_weasyprint import HTML, render_pdf File "c:\program files\python38\lib\site-packages\flask_weasyprint\__init__.py", line 5, in <module> import weasyprint File "c:\program files\python38\lib\site-packages\weasyprint\__init__.py", line 336, in <module> from .css import preprocess_stylesheet # noqa isort:skip File "c:\program files\python38\lib\site-packages\weasyprint\css\__init__.py", line 25, in <module> from . import computed_values, counters, media_queries File "c:\program files\python38\lib\site-packages\weasyprint\css\computed_values.py", line 9, in <module> from ..text.ffi import ffi, pango, units_to_double File "c:\program files\python38\lib\site-packages\weasyprint\text\ffi.py", line 398, in <module> gobject = _dlopen( File "c:\program files\python38\lib\site-packages\weasyprint\text\ffi.py", line 385, in _dlopen return ffi.dlopen(names[0]) # pragma: no cover File "c:\program files\python38\lib\site-packages\cffi\api.py", line 150, in dlopen lib, function_cache = _make_ffi_library(self, name, flags) File "c:\program files\python38\lib\site-packages\cffi\api.py", line 832, in _make_ffi_library backendlib = _load_backend_lib(backend, libname, flags) File "c:\program files\python38\lib\site-packages\cffi\api.py", line 827, in _load_backend_lib raise OSError(msg) OSError: cannot load library 'gobject-2.0-0': error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called 'gobject-2.0-0'
What do I miss or what did I do wrong?
Previously I used:
Python:
APP.route("/to-pdf/<string:id>")
def to_pdf(id):
...
html = render_template('pdf.html', id=id)
return render_pdf(HTML(string=html))
HTML: <a href="/to-pdf/{{id}}" target="_blank">
And it worked as expected. Upon clicking the a-tag the browser would display the pdf in a new tab. However I decided that i wanted a specific filename for when users downloaded the pdf from the browser. so i changed the Python to:
APP.route("/to-pdf/<string:id>")
def to_pdf(id):
...
html = render_template('pdf.html', id=id)
pdf_filename = "PDF-" + id
return render_pdf(HTML(string=html), download_filename=pdf_filename)
As per the flask-weasyprint documentation. Now, however, upon clicking the a-tag a new tab does not open, and it just downloads directly to the computer without a preview. It still generates the same pdf, but I would like it to keep the functionality as before with the addition of a default custom filename. So basically I'm wondering how i can set the default filename for downloading a file, without changing the url and while still allowing the pdf to be viewable in the browser (i.e. not download directly to the computer). Thanks
Hi, I got the assertion error when I called flask_weasyprint render_pdf method
My Code:
html = render_template('report.html', stress_data=#####, steps_data=#####, user_data=#####,
stress_img=#####, steps_img=#####)
pdf = render_pdf(HTML(string=html))
Error:
File "/usr/local/lib/python3.9/dist-packages/weasyprint/layout/block.py", line 299, in _linebox_layout
for i, (line, resume_at) in enumerate(lines_iterator):
File "/usr/local/lib/python3.9/dist-packages/weasyprint/layout/inline.py", line 43, in iter_line_boxes
line, resume_at = get_next_linebox(
File "/usr/local/lib/python3.9/dist-packages/weasyprint/layout/inline.py", line 114, in get_next_linebox
offset_x = text_align(
File "/usr/local/lib/python3.9/dist-packages/weasyprint/layout/inline.py", line 1134, in text_align
assert align == 'end'
Can you please fix that. Thanks
The problem is caused by the default FW dispatcher crashing on "data:" URLs, as there's no hostname in these URLs.
We can add a try/except around dispatcher()
(line 122), logging the error as warning and setting result
to None. This would allow dispatchers to fail and try the next dispatcher as a fallback. Yes, we can fix the default dispatcher too :).
I install with pip3 (python3.8 default on platform):
$pip3 install Flask-WeasyPrint
and it fails on cairo import in flask_weasyprint/tests.py
once I substitute it with cairocffi, it works but tests now report errors
Traceback (most recent call last):
File "/home/silpol/dev/Flask-WeasyPrint/flask_weasyprint/tests.py", line 161, in test_dispatcher
assert_app('http://a.net/b', '', '/b', '/')
File "/home/silpol/dev/Flask-WeasyPrint/flask_weasyprint/tests.py", line 151, in assert_app
assert json.loads(dispatcher(url)['string']) == {
File "/home/silpol/dev/Flask-WeasyPrint/flask_weasyprint/init.py", line 147, in flask_url_fetcher
raise ValueError('Flask-WeasyPrint got HTTP status %s for %s%s'
ValueError: Flask-WeasyPrint got HTTP status 308 PERMANENT REDIRECT for http://a.net/bb''
Traceback (most recent call last):
File "/home/silpol/dev/Flask-WeasyPrint/flask_weasyprint/tests.py", line 49, in test_wrappers
assert hasattr(html, 'root_element')
AssertionError
Ran 7 tests in 0.237s
FAILED (failures=1, errors=1)
My 'entry' view is protected with '@login_required'. When attempting to render a PDF using the code below it seems that WeasyPrint is not acknowledged as a logged in user and thus is kicked out and ends up creating a PDF of my login screen instead. Using Flask command return redirect(url_for('entry', id = 452))
, however, works fine. Any idea how to make this work?
@app.route('/pdf.pdf')
@login_required
def pdf():
return render_pdf(url_for('entry', id = 452)) # CREATES PDF OF LOGIN SCREEN INSTEAD
# return redirect(url_for('entry', id = 452)) # WORKS
To customize my PDF using another library, I performed some validations on the HTML itself to decide how I should customize it. An example would be:
{% if variable == "Blue"%}
{{my-variable}}
I can't use the {% extends "template-pdf.html"%} parameters in this type of pdf?
Hi Kozea.
First of all, thanks for building this amazing tool for generating beautiful PDF report! We have used it in production and it is working perfectly!
I am planning to render the layout into webpage which will help me coding productively, now weasyprint flask works fine but I observed that it can't reload when I modify HTML or css, I have to click shift+cmd+r
for full-refresh.
Do you know anyway to reload for instance every a couple of seconds or everytime the HTML/CSS sources modified?
Thanks!
kwargs['url_fetcher'] is always overriden when instanciating HTML().
I would like to define a custom url_fetcher. Is there a specific reason why we can't ?
I'm unable to install the Flask-WeasyPrint module from my requirements.txt file. I'm running an Ubuntu 14.04 box using Python2.7. When I try and install module I get the following error;
Collecting html5lib>=0.999999999 (from WeasyPrint>=0.12->Flask-WeasyPrint==0.5->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/a5/62/bbd2be0e7943ec8504b517e62bab011b4946e1258842bc159e5dfde15b96/html5lib-1.0.1-py2.py3-none-any.whl (117kB)
Collecting tinycss2>=0.5 (from WeasyPrint>=0.12->Flask-WeasyPrint==0.5->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/88/95/0ec73db7fc638ec000e662936ffe1a4e1eaa22f2861c8de18b1597c42584/tinycss2-0.6.1-py2.py3-none-any.whl (61kB)
Collecting cssselect2>=0.1 (from WeasyPrint>=0.12->Flask-WeasyPrint==0.5->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/12/e2/91fcd4cd32545beec6e11628d64d3e20f11b5a95dd1ccf3216fd69f176b7/cssselect2-0.2.1-py2.py3-none-any.whl
Collecting cffi>=0.6 (from WeasyPrint>=0.12->Flask-WeasyPrint==0.5->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/14/dd/3e7a1e1280e7d767bd3fa15791759c91ec19058ebe31217fe66f3e9a8c49/cffi-1.11.5-cp27-cp27mu-manylinux1_x86_64.whl (407kB)
Collecting cairocffi>=0.5 (from WeasyPrint>=0.12->Flask-WeasyPrint==0.5->-r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/62/be/ad4d422b6f38d99b09ad6d046ab725e8ccac5fefd9ca256ca35a80dbf3c6/cairocffi-0.9.0.tar.gz (84kB)
Complete output from command python setup.py egg_info:
c/_cffi_backend.c:15:17: fatal error: ffi.h: No such file or directory
#include <ffi.h>
^
compilation terminated.
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/tmp/pip-build-dbkNN5/cairocffi/setup.py", line 51, in <module>
'test': ['pytest-runner', 'pytest-cov'],
File "/usr/local/lib/python2.7/distutils/core.py", line 111, in setup
_setup_distribution = dist = klass(attrs)
File "/usr/local/lib/python2.7/site-packages/setuptools/dist.py", line 269, in __init__
self.fetch_build_eggs(attrs['setup_requires'])
File "/usr/local/lib/python2.7/site-packages/setuptools/dist.py", line 313, in fetch_build_eggs
replace_conflicting=True,
File "/usr/local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 826, in resolve
dist = best[req.key] = env.best_match(req, ws, installer)
File "/usr/local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1092, in best_match
return self.obtain(req, installer)
File "/usr/local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1104, in obtain
return installer(requirement)
File "/usr/local/lib/python2.7/site-packages/setuptools/dist.py", line 380, in fetch_build_egg
return cmd.easy_install(req)
File "/usr/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 665, in easy_install
return self.install_item(spec, dist.location, tmpdir, deps)
File "/usr/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 695, in install_item
dists = self.install_eggs(spec, download, tmpdir)
File "/usr/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 876, in install_eggs
return self.build_and_install(setup_script, setup_base)
File "/usr/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1115, in build_and_install
self.run_setup(setup_script, setup_base, args)
File "/usr/local/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 1103, in run_setup
raise DistutilsError("Setup script exited with %s" % (v.args[0],))
distutils.errors.DistutilsError: Setup script exited with error: command 'gcc' failed with exit status 1
Am I missing any dependencies? I've tried to install the WeasyPrint python modules:
build-essential python-dev python-pip python-cffi libcairo2 libpango1.0-0 libpangocairo-1.0.0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info
But I'm still not able to install Flask-WeasyPrint. What gives? I'm I missing something.
in Mobile view, render_pdf does not work and hold on rendering
Paged media CSS doesn't support more complex page header/footer requirements, like tables. A solution to this is to create a separate page with such a header, and merge this into the PDF on the required pages. A proof of concept was written by pikhovkin in this Gist.
I made a function to use this functionality with WeasyPrint, and would like to create a pull request to include this into Flask-WeayPrint, since it is such a common use-case.
(any comments about my coding is welcome, since I'm new to the Python language and community)
My API is currently like this:
first_page = lambda page_nr: page_nr==0
not_first_page = lambda page_nr: page_nr!=0
odd_page = lambda page_nr: page_nr%2==1
even_page = lambda page_nr: page_nr%2==0
class Overlay(object):
def __init__(self, template_name_or_list, fn_include_on_page=not_first_page, **kwargs):
def render_pdf_with_overlays(html, *overlays, stylesheets=None, download_filename=None):
#example:
html = flask.render_template('my_report.html')
first_page_overlay = Overlay('first_page_overlay.html', fn_include_on_page=first_page, left='10cm', top='5cm')
default_page_overlay = Overlay('default_page_overlay.html', fn_include_on_page=not_first_page)
pdf_response = render_pdf_with_overlays(HTML(string=html), first_page_overlay, default_page_overlay)
Overlay
: Represents one HTML page to be overlaid on a PDF document.
template_name_or_list
: the name of the HTML template, which is resolved with jinja2's get_or_select_template method.fn_include_on_page
: a function that takes a 0-based page number, and returns a boolean that indicates if it needs to be included on that page.kwargs
: context used to render the overlay. Can also be used to dynamically position content.render_pdf_with_overlays
renders the PDF like Flask-WeasyPrint's render_pdf
, but with overlays.
stylesheets
are also used to render the Overlay, so if any FontConfiguration is included, it is also included in the Overlays.overlays
templates are rendered to HTML with the supplied context, and this context is extended with the page
and pages
entries, indicating current 1-based page number and number of pages (CSS page and pages counters don't work with single page overlays)A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.