Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
weasyprint
: Printing documents using WeasyPrint¶
The lino.modlib.weasyprint
plugin installs two build methods for
generating printable documents using weasyprint.
Applications that use this plugin will automatically install the ‘weasyprint’
Python package when the server administrator runs install
.
The two build methods defined by this plugin both use the same input template,
whose ending must be .weasy.html
. Both methods then render the input
template through Jinja with the standard context variables (defined by
get_printable_context
.
The base build method WeasyBuildMethod
then returns this HTML
output “as is”, the other method runs weasyprint over the HTML file to convert
it to a .pdf
file.
Examples in this document use the lino_book.projects.tera1
demo
project.
>>> from lino import startup
>>> startup('lino_book.projects.tera1.settings.doctests')
>>> from lino.api.shell import *
>>> from lino.api.doctest import *
See also printing : Basic printing functionality.
Build methods¶
This plugin defines no models, it just adds two build methods to your the global
list of build methods (lino.modlib.printing.BuildMethods
).
- class lino.modlib.weasyprint.WeasyBuildMethod¶
The base class for both build methods.
- class lino.modlib.weasyprint.WeasyHtmlBuildMethod¶
Renders the input template and returns the unmodified output as plain HTML.
- class lino.modlib.weasyprint.WeasyPdfBuildMethod¶
Like
WeasyBuildMethod
, but the rendered HTML is then passed through weasyprint which converts from HTML to PDF.
Templates¶
- weasyprint/base.weasy.html¶
The base template. Defines the general HTML and CSS and block definitions to be used by every weasyprint template. See the source code.
Actual templates use the base template by starting adding the following line:
{%- extends "weasyprint/base.weasy.html" -%}
Examples of weasyprint templates¶
Here is a list of weasyprint templates that use the base template. You can use them as examples for your own work. We also use this list for manual end-user testing.
In demo project
lino_book.projects.cosi1
, go to and print one of them. (templatetrading/VatProductInvoice/default.weasy.html
inlino_xl.lib.trading
)In demo project
lino_book.projects.tera1
, go to and print one of them. (templatebevats/Declaration/default.weasy.html
inlino_xl.lib.bevats
)In demo project
lino_book.projects.tera1
, go to , click on one of the partners, then click Print. (templatecontacts/Partner/payment_reminder.weasy.html
inlino_xl.lib.accounting
)In demo project
lino_book.projects.tera1
, go to , double-cick on one of them to open the detail window, and then click “Members” or “Members (HTML)” in the Print field. (templatelino_xl.lib.lists
inlists/List/list_members.weasy.html
)In demo project
lino_book.projects.tera1
, go to , then click the print button (templatesheets/Report/default.weasy.html
inlino_xl.lib.sheets
).In demo project
lino_book.projects.voga2
, open the detail view of some course and click on one of the Presence sheet links. Try several date ranges and options. (templatecourses/Course/presence_sheet.weasy.html
inlino_xl.lib.courses
)lino_xl.lib.working
–working/ServiceReport/default.weasy.html
In demo project
lino_book.projects.avanti1
, go to some client and click the print button. (templateavanti/Client/final_report.weasy.html
inlino_avanti.lib.clients
)
Here is a list of the weasy templates included with the Lino Extensions Library:
>>> import lino_xl
>>> from os.path import dirname
>>> from atelier.sheller import Sheller
>>> shell = Sheller(dirname(lino_xl.__file__))
>>> shell("find -name '*.weasy.html' | sort")
...
./lib/accounting/config/contacts/Partner/payment_reminder.weasy.html
./lib/agenda/config/cal/Event/base.weasy.html
./lib/agenda/config/cal/Event/default.weasy.html
./lib/bevats/config/bevats/Declaration/default.weasy.html
./lib/courses/config/courses/Course/description.weasy.html
./lib/courses/config/courses/Course/presence_sheet.weasy.html
./lib/excerpts/config/excerpts/base.weasy.html
./lib/lists/config/lists/List/list_members.weasy.html
./lib/orders/config/orders/Order/base.weasy.html
./lib/orders/config/orders/Order/default.weasy.html
./lib/products/config/products/Product/product_barcode.weasy.html
./lib/sheets/config/sheets/Report/default.weasy.html
./lib/storage/config/storage/DeliveryNote/base.weasy.html
./lib/storage/config/storage/DeliveryNote/default.weasy.html
./lib/subscriptions/config/subscriptions/Subscription/base.weasy.html
./lib/subscriptions/config/subscriptions/Subscription/default.weasy.html
./lib/trading/config/trading/VatProductInvoice/base.weasy.html
./lib/trading/config/trading/VatProductInvoice/default.weasy.html
Note that excerpts, orders and trading have their own
FOO/base.weasy.html
templates, which inherit from the main base
weasyprint/base.weasy.html
.
For other usage examples see the specs of Lino Welfare.
Warnings about Cairo and Pango¶
This plugin installs a warnings filter for the cffi.model module in
order to get rid of a disturbing warning There are known
rendering problems with Cairo <= 1.14.0
and @font-face
support needs Pango >= 1.38
issued by weasyprint.
How it all works¶
What happens when I print an invoice?
When Lino starts up, it finds the excerpt type for trading invoices (more
precisely the trading.VatProductInvoice
model) and therefore installs the print
action on that model. This is why you a have a print button per invoice.
The excerpt type tells Lino which build method you want to use
for building your printable document. The default build method is weasypdf
.
When we know the build method, we can compute the name of the template to use.
This name is a combination
of trading/VatProductInvoice
(the plugin and model name) and
default.weasy.html
(the default template filename for weasypdf when
lino_xl.lib.excerpts.ExcerptType.template
is empty).
Lino now searches for a file named trading/VatProductInvoice/default.weasy.html
.
This file can exist under any config
directory.
If you have a local config
directory, this is searched first.
Otherwise Lino uses a default file from the source code directory.
More about config directories in Introduction to config directories.
Now look at the default trading/VatProductInvoice/default.weasy.html
template file. The first line is:
{%- extends "weasyprint/base.weasy.html" -%}
Which means that Lino first loads yet another template, called
weasyprint/base.weasy.html
.
How weasyprint templates work¶
The weasyprint template uses the CSS @-rules @page and @bottom-right, which define styles to apply to individual pages when printing the document. That is, they are used to apply styles for paged media only, not for continuous media like a browser window.
List of all page-margin
properties:
https://www.quackit.com/css/at-rules/css_page-margin_properties_list.cfm
Setting the height attribute in HTML is called a “presentational hint” and it’s now recommended not to use them and use CSS instead. Presentational hints are ignored by WeasyPrint by default, but you can handle them using the –presentational-hints CLI parameter. https://github.com/Kozea/WeasyPrint/issues/872
Lino currently doesn’t use arbitrary “complex” HTML in headers and footers (as documented here). The standard system with at-rules works well for us.
It contains pseudo-elements for styling the first page as well as the left and right margins of the page.
It can contain something like this:
<style type="text/css">
@page {
@top-right {
height: 20mm;
padding: 0px;
text-align: right;
content: url(file://{{logo_file}});
}
</style>
More readings:
https://github.com/Kozea/WeasyPrint/blob/gh-pages/samples/invoice/invoice.css
https://gist.github.com/pikhovkin/5642563 complex headers
Related work: