【Django】ページをPDF出力する(セッション)【Python】

# 初めに
※以下の記事の続きです。未読の場合は先に目を通してください。
[【Django】ページをPDF出力する(オプション)【Python】](https://qiita.com/nagisa_O/items/59be49e513cac1c2546d)

前回、pdfkitのオプションのcookieにセッションIDを設定することで、
pdfkitのリクエストにセッションIDを持たせられることを確認しました。
これによりセッションで自身とpdfkitの値の受け渡しができるようになりますので、動きを検証します。

<font color="Red">注意：この記事は不完全です。最後までお読みください。</font>

# 環境
|名称  |バージョン  |
|---|---|
|Python  |3.10.4  |
|Django  |4.0.6 |
|pdfkit  |1.0.0 |

# 検証するページ
前回までpdf出力を行っていたページに、1行だけ出力するボタンを追加しました。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/31401933-b8b1-4901-3c04-525c91f12bff.jpeg)

body部は以下のように変更してあります。
値はDBから取得したものを表示し、pdf列の出力ボタン押下時にIDを渡します。
```php:index.html
    <table class="table">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">First</th>
            <th scope="col">Last</th>
            <th scope="col">pdf</th>
          </tr>
        </thead>
        <tbody>   
          {% for item in lists %}
            <tr>
              <th scope="row">{{ item.id }}</th>
              <td>{{ item.first_name }}</td>
              <td>{{ item.last_name }}</td>
              <td>
                <form action="to_pdf_alone/" method="post">
                  {% csrf_token %}
                  <input type="hidden" value="{{ item.id }}" name="id">
                  <button type="submit" class="btn btn-success">出力</button>
                </form>
              </td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
      <form action="to_pdf/" method="post">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">pdf出力</button>
      </form>
```

# やりたいこと
ようやくやりたいことの準備が整ったので、ここで目的を明確にします。
これまでの検証は、以下の流れを実現したくて検証していました。
ユーザ操作の選択によってDBアクセスのキーが確定し、それを元に作成されたページをpdf出力したい、というのが重要なポイントです。

---------------------------フロントエンド-------------------------
1.ユーザ操作で出力のボタンが押される
2.選択された対象のPK(今回はID)をバックエンドに渡す
---------------------------バックエンド---------------------------
3.セッションにPKをセットする
4.pdfkitを呼び出す(この際にセッションIDを渡す)
5.pdfkitがセッションからPKを取り出し、PKをキーにDBアクセスする
6.DBから取得した値をフロントに戻す
---------------------------フロントエンド-------------------------
7.1件だけ表示されたページをpdf出力する

# セッションで値の受け渡し
pdf列の出力ボタン押下時に呼び出される関数は以下のようになっています。
受け取った値をセッションにセットし、pdfkitにセッションIDを設定して呼び出しています。
```php:views.py
def to_pdf_alone(request):
    # idを受け取る
    id = request.POST.get('id')

    # idをセッションにセットする
    request.session['id'] = id

    url = 'http://127.0.0.1:8000/test_app/detail/'
    cookie_list = request.COOKIES
    options = {
            'cookie': [
                ('sessionid', cookie_list['sessionid']),
            ]
          }
    pdfkit.from_url(url, 'sample.pdf', options=options)
    return redirect('test_app:index')

```

pdfkitに渡されたurlは以下の関数にルーティングされています。
セッションIDを受け取ったpdfkitはセッションから値を取得し、その値でDBアクセスします。
```php:views.py
def detail(request):
    # idをセッションから受け取る
    id = request.session.get('id')

    # idをキーにDBアクセス
    person = Person.objects.filter(id=id)
    
    context = {'item': {'id': person[0].id, 'first_name': person[0].first_name, 'last_name': person[0].last_name}}
    return render(request, 'test_app/detail.html', context)

```

pdfkitがpdf出力するページは、渡された1件分の値を受け取り表示するだけの簡単なものです。
body部は以下のようになっています。
```php:detail.html
    <table class="table">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">First</th>
            <th scope="col">Last</th>
          </tr>
        </thead>
        <tbody>   
            <tr>
              <th scope="row">{{ item.id }}</th>
              <td>{{ item.first_name }}</td>
              <td>{{ item.last_name }}</td>
            </tr>
        </tbody>
    </table>
```

# 出力確認
では適当にpdf列のボタンを押下し、出力を確認します。
![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/93e48555-0296-42a9-8e1a-56bc0621edc8.jpeg)
1件のみの出力が確認できました。

# まとめ
今回までで前述の「やりたいこと」内でまとめた流れを実現できました。
これだけのことに記事3つ分も費やしてご苦労様です。疲れてしまいましたね。
ですがこれで思う存分ページをpdf化できます！
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
...と思っていましたが、pdf列のボタンをポチポチ押して遊んでいてあることに気が付きました。
<font color="Red">__なんか、出力される値が、遅れてない？__</font>

以下障害対応
[【Django】ページをPDF出力する(障害対応)【Python】](https://qiita.com/nagisa_O/items/4ffd8777f716664affca)