xhtml2pdf Пиза css не работает ни один функционал

Я пытаюсь сгенерировать PDF с использованием html+css с использованием xhtml2pdf.pisa с использованием Django. Тем не менее, я сталкиваюсь со всевозможными странными проблемами с CSS.

Ниже мой код:

from django.template.loader import render_to_string
import cStringIO as StringIO
import xhtml2pdf.pisa as pisa
import cgi, os
def fetch_resources(uri, rel):
    path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
    return path
def test_pdf(request):
    html = render_to_string('pdf/quote_sheet.html', { 'pagesize':'A4', }, context_instance=RequestContext(request))
    result = StringIO.StringIO()
    pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), dest=result, link_callback=fetch_resources)
    if not pdf.err:
        return HttpResponse(result.getvalue(), mimetype='application/pdf')
    return HttpResponse('Gremlins ate your pdf! %s' % cgi.escape(html))

И мой шаблон:

<!DOCTYPE HTML PUBLIC "-//W3C/DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    {% load static from staticfiles %}
    {% load i18n %}
    <meta charset="utf-8"/>
    <meta http-equiv="content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="content-language" content='{% trans "g_locale2" %}'/>
    <title>{% block title %}{% endblock %}</title>
    <style type="text/css">
        @page {
            size: A4;
            margin: 1cm;
            @frame footer {
                -pdf-frame-content: footerContent;
                bottom: 0cm;
                margin-left: 9cm;
                margin-right: 9cm;
                height: 1cm;
                font-family: "Microsoft JhengHei";
            }
        }
        @font-face {
            font-family: "Microsoft JhengHei";
            src:url('{% static "ttf/msjh.ttf" %}');
        }
        @font-face {
            font-family: "Microsoft JhengHei";
            src:url('{% static "ttf/msjhbd.ttf" %}');
        }
        @font-face {
            font-family: "Helvetica";
            src:url('{% static "ttf/Helvetica_Reg.ttf" %}');
        }
        table.styled-table tr th {
            color: gray;
            background-color: blue;
            font-size: 14px;
            font-family:"Microsoft JhengHei";
            border: 1px solid black;
        }
        .biz_phone, .biz_fax {
            display: inline-block;
            width: 100px;
            line-height: 32px;
        }
        .biz-info {
            margin-bottom: 20px;
        }
    </style>
    <link rel="stylesheet" href='{% static "css/pdf.css" %}'/>
</head>
<body>
    <div id="main-content">
        <div class="container">
            <div class="biz-info">
                <div class="biz_name">{{ proj.biz.name }}</div>
                <div class="biz_address">{{ proj.biz.address }}</div>
                <div class="biz_phone">{{ proj.biz.phone }}</div>
                <div class="biz_fax">{{ proj.biz.fax }}</div>
            </div>
            <div class="table-div">
                <table class="styled-table">
                    <tr class="row_header">
                        <th class="col_order">{% trans "g_item_num" %}</th>
                        <th class="col_name">{% trans "g_item_name" %}</th>
                        <th class="col_provider">{% trans "g_provider_name" %}</th>
                        <th class="col_budget_quantity">{% trans "g_quantity" %}</th>
                        <th class="col_price">{% trans "g_item_price" %}</th>
                        <th class="col_total_price">{% trans "g_item_total" %}</th>
                    </tr>
                </table>
           </div>
        </div>
    </div>
</body>
</html>

Мой код довольно простой и ничего особенного, они просто в значительной степени скопированы из Интернета. У меня много странных проблем:

  1. font-size, background-color работает во внешнем css, но только при применении к тегу body или html.
  2. ширина, высота строки и т. д. не работают вообще, независимо от того, являются ли они внешними, внутренними или встроенными.
  3. margin-bottom родительского div применяется к каждому дочернему div вместо родительского div...
  4. все виды других случайных вопросов...

Я не могу наблюдать паттерн от этих симптомов, кроме как просто думать, что синтаксический анализатор и механизм компоновки CSS просто полностью неполон и не функционирует. Однако я не могу найти никого в Интернете, кто имеет те же проблемы, что и я. Я сумасшедший? Я не уверен, что здесь происходит... любая помощь будет оценена.

1 ответ

Под одеялом, xhtml2pdf использования reportlab на самом деле создать PDF.

Делая некоторую отладку - я следил за выполнением parser.py в xhtml2pdf чтобы увидеть, смогу ли я выяснить, где CSS "пропадает" или применяется к неправильным элементам.

Я обнаружил, что CSS был успешно проанализирован, и перевод на фрагменты документа (здесь в коде) работает нормально, с правильными элементами CSS, применяемыми к правильным элементам.

Я считаю, что проблема связана с reportlab движок рендеринга PDF. Это задокументировано здесь. Он не имеет отображения 1:1 между CSS и директивами, которые вы можете передать в него.

Я впервые узнал об этом, отвечая на этот вопрос. Например, в разделе рендеринга таблицы reportlab документация (руководство пользователя с открытым исходным кодом, глава 7, стр. 76), очевидно, что аналога для border-style Атрибут CSS - поэтому, хотя в теории вы можете указать стиль границы и не будет выдано никакой ошибки, это значение будет игнорироваться.

Исследуя сопоставление CSS и PDF, я обнаружил это программное обеспечение (Javascript), которое также отображает HTML/CSS в PDF. Я попробовал это на HTML из этого вопроса и другого, на который я ссылался. Это позволяет правильно отобразить страницы в PDF-документе, поэтому я считаю, что это не принципиальное ограничение спецификации PDF-документа, а скорее reportlab модуль.

Мне кажется, это проблема для xhtml2pdf, Это выглядит особенно плохо для таблиц, но, очевидно, влияет и на другие типы документов. Извините, что не решил вашу проблему, но я надеюсь, что это поможет объяснить это.

Другие вопросы по тегам