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. width, line-height и т. д. не работают вообще, вне зависимости от того, внешний, внутренний или встроенный.
  3. margin-bottom на родительском div применяется к каждому дочернему div вместо родительского div ...
  4. всевозможные другие случайные проблемы ...

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


person pinghsien422    schedule 20.06.2015    source источник
comment
Я видел такое поведение xhtml2pdf в другом контексте, отвечая на другой вопрос здесь. Постараюсь покопаться в этом подробнее, теперь вижу, что это не единичная проблема   -  person J Richard Snape    schedule 20.06.2015
comment
К вашему сведению, это подходящий ответ - см. Мою заметку о стиле границы для элемента таблицы stackoverflow.com/questions/24574976/   -  person J Richard Snape    schedule 21.06.2015
comment
Я прочитал ваш ответ в ссылке, я не совсем уверен ... вы предлагаете мне использовать matplotlib вместо таблицы рендеринга? проблема не только в таблицах, но и в div. Я внес некоторые изменения в код, стиль .biz_phone, .biz_fax {display: inline-block; } работает, но ширина и высота строки - нет, и .biz-info {margin-bottom: 20px; } применяется ко всем дочерним div biz_name, biz_address, biz_phone, biz_fax, но вместо этого он должен применяться только к biz-info ... Мы говорим не только об игнорировании CSS, но и о неправильном применении CSS.   -  person pinghsien422    schedule 21.06.2015
comment
Извините, я должен был быть более ясным. Я просто комментирую, что видел подобное поведение - это не ваша ошибка, пока не предлагаю решение. Если у меня что-то получится, я отправлю ответ.   -  person J Richard Snape    schedule 21.06.2015
comment
в порядке. Большое спасибо. Если у вас что-то получится, дайте мне знать !!!   -  person pinghsien422    schedule 21.06.2015
comment
Я добавил ответ ниже - не уверен, помогает ли это вообще? Это не хорошие новости, но я думаю, что все сводится к базовому модулю reportlab.   -  person J Richard Snape    schedule 25.06.2015


Ответы (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. Это кажется особенно плохим для таблиц, но, очевидно, влияет и на другие типы документов. Извините, что не могу решить вашу проблему, но я надеюсь, что это поможет ее объяснить.

person J Richard Snape    schedule 24.06.2015