読者です 読者をやめる 読者になる 読者になる

[[ともっくす alloc] init]

ともっくすの雑多な日記と技術的なメモ

ReportLabで生成したPDFをPyramidで表示させたい

ReportLabでPDFを生成する方法も,Pyramidの使い方も少しだけわかった.

というわけで,その両者を一緒に使いたい.


プロジェクトshowpdfを作成し,各ファイルを以下のように変更する.

__init__.py

from pyramid.config import Configurator


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.add_route('pdf', '/pdf') # 追加
    config.scan()
    return config.make_wsgi_app()

views.py

from pyramid.response import Response
from pyramid.view import view_config

import StringIO
import os

from reportlab.pdfgen import canvas

@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
    pdf_url = request.route_url("pdf")
    return dict(pdf_url=pdf_url)


@view_config(route_name='pdf')
def pdf_view(request):
    # data = _prepare_output_data_with_StringIO()
    data = _prepare_output_data_with_reading_file()
    return Response(body=data, content_type="application/pdf")


# StringIOを使った方法
def _prepare_output_data_with_StringIO():
    pdf = StringIO.StringIO()
    _make_pdf(pdf)
    data = pdf.getvalue()
    pdf.close()
    return data


# ファイルオープンを使った方法
def _prepare_output_data_with_reading_file():
    filename = "./file.pdf"
    _make_pdf(filename)
    data = open(filename,"rb").read()
    os.unlink(filename)
    return data


# ReportLabでPDFを生成する
def _make_pdf(output):
    pdf_canvas = canvas.Canvas(output)
    pdf_canvas.saveState()
    pdf_canvas.rect(150, 500, 200, 250)
    pdf_canvas.restoreState()
    pdf_canvas.save()

mytemplate.pt

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8"/>
    <title>showpdf</title>
  </head>
  <body>
    <a href=${pdf_url}>pdf生成</a>
  </body>
</html>


PDFを表示する方法としては,StringIOを使う方法とファイルをオープンする方法があるらしい.

それぞれ,_prepare_output_data_with_StringIO()と_prepare_output_data_with_reading_file()で行なっている.

pdf_view(request)で使用するメソッドを変更すれば,どちらの方法も使える.

で,pdf_view(request)で返すResponseのcontent_typeをapplication/pdfとすることで,PDFが扱える.


ファイルオープンを使う方法の場合,ファイルを書き出す権限がないというエラーが出る場合があるので,apacheが権限を持っているようなディレクトリにファイルの書き出し等を行う必要があるかもしれない.


実行した結果は以下みたいな感じ.(めちゃくちゃ拡大表示中)
f:id:o_tomox:20130808213031p:plain

「pdf生成」のリンクをクリックすると,PDFが生成・表示される.
f:id:o_tomox:20130808213141p:plain


今回はただのリンクで生成しているが,フォーム等を使うことで,いろいろ広がるでしょう.


参考にさせていただいたサイト様