Оптимизировать преобразование PDF в Django / Python - PullRequest
1 голос
/ 03 августа 2010

У меня есть веб-приложение, которое экспортирует отчеты в PDF. Все хорошо, когда запрос возвращает менее 100 значений. Когда число записей поднимается выше 100, сервер выдает ошибку 502 Proxy. Отчет выводит нормально в HTML. Процесс, который вешает сервер, - это преобразование HTML в PDF. Я использую xhtml2pdf (AKA pisa 3.0) для создания PDF. Алгоритм примерно такой:

<code>def view1(request, **someargs):
    queryset = someModel.objects.get(someargs)
    if request.GET['pdf']:
        return pdfWrapper('template.html',queryset,'filename')
    else:
        return render_to_response('template.html',queryset)

def pdfWrapper(template_src, context_dict, filename):
    ################################################
    #
    # The code comented below is an older version
    # I updated the code according the comment recived
    # The function still works for short HTML documents
    # and produce the 502 for larger onese
    #
    ################################################

    ##import cStringIO as StringIO
    import ho.pisa as pisa
    from django.template.loader import get_template
    from django.template import Context
    from django.http import HttpResponse
    ##from cgi import escape

    template = get_template(template_src)
    context = Context(context_dict)
    html  = template.render(context)

    response = HttpResponse()
    response['Content-Type'] ='application/pdf'
    response['Content-Disposition']='attachment; filename=%s.pdf'%(filename)

    pisa.CreatePDF(
        src=html,
        dest=response,
        show_error_as_pdf=True)

    return response

    ##result = StringIO.StringIO()
    ##pdf = pisa.pisaDocument(
    ##            StringIO.StringIO(html.encode("ISO-8859-1")),
    ##            result)
    ##if not pdf.err:
    ##    response = HttpResponse(
    ##                   result.getvalue(), 
    ##                   mimetype='application/pdf')
    ##    response['Content-Disposition']='attachement; filename=%s.pdf'%(filename)
    ##    return response
    ##return HttpResponse('Hubo un error<pre>%s
'% escape (html))

Я подумал о создании буфера, чтобы сервер мог освободить память, но пока ничего не нашел. Кто-нибудь может помочь? пожалуйста?

1 Ответ

3 голосов
/ 04 августа 2010

Я не могу точно сказать, что является причиной вашей проблемы - это может быть вызвано проблемами с буферизацией в StringIO.

Однако вы ошибаетесь, если предполагаете, что этот код будет фактически передавать сгенерированные данные PDF: StringIO.getvalue () возвращает содержимое строкового буфера во время вызова этого метода, а не выходной поток (см. http://docs.python.org/library/stringio.html#StringIO.StringIO.getvalue).

Если вы хотите транслировать вывод, вы можете рассматривать экземпляр HttpResponse как файлоподобный объект (см. http://docs.djangoproject.com/en/1.2/ref/request-response/#usage).

Во-вторых, я не вижу никакой причинычтобы использовать здесь StringIO. В соответствии с документацией Пизы, которую я обнаружил (кстати, она вызывает эту функцию CreatePDF), источником может быть строка или объект Unicode.

Лично я бы попробовал следующее:

  1. Создание HTML в виде строки Unicode
  2. Создание и настройка объекта HttpResponse
  3. Вызов генератора PDF со строкой в ​​качестве ввода и ответом в качестве вывода

В общих чертах это может выглядеть следующим образом:

html = template.render(context)

response = HttpResponse()
response['Content-Type'] ='application/pdf'
response['Content-Disposition']='attachment; filename=%s.pdf'%(filename)

pisa.CreatePDF(
    src=html,
    dest=response,
    show_error_as_pdf=True)

#response.flush()
return response

Однако я не попытался, если это действительно работает. (Я делал этот вид потоковой передачи PDFнаПока только в Java.)

Обновление: Я только что посмотрел на реализацию HttpResponse.Он реализует файловый интерфейс, собирая фрагменты строк, записанных в него, в список.Вызывать response.flush () бессмысленно, потому что он ничего не делает.Кроме того, вы можете установить параметры ответа, такие как Content-Type, даже после того, как ответ был получен как файл-объект.

Ваша первоначальная проблема также может быть связана с тем фактом, что вы никогда не закрывали объекты StringIO.Базовый буфер объекта StringIO не освобождается до вызова close ().

...