This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

[Day 30]セッションへのデータの保存と読み出し

Last updated at Posted at 2021-02-08

February 8, 2021
←前回:Day 29 Djangoでメールを送信する

「Djangoを学びたい」とのことでありましたら[Day 1]Djangoの開発環境から読むことをおすすめします。

はじめに

掲示板アプリもそれっぽくなってきましたね。あと少し頑張りましょう。

今回はセッションの使い方を学ぶための実装を例示しますが、学習用に用意したため掲示板の機能にはあまり影響がありません。予めご了承下さい。

セッション

セッションについては公式ドキュメントも参照してください。Djangoのセッションは完全にクッキーベースでありセッションIDをURLとして渡す等の手法は用いません。また、セッションとはブラウザが起動中のみ有効でブラウザと閉じると切れるものと考えている方もいるかも知れませんが、Djangoの標準設定ではセッションはブラウザを閉じても生き続ける永続的なもので、意図的に削除されるか、有効期限(標準設定では2週間)となるまで削除されません。もちろん、ブラウザを閉じたらセッションも切れるようにも設定出来ます。

セッションを使ったトピック作成画面

確認画面付きのトピック作成画面を作るで作成したトピック作成画面をセッションを用いる方式に修正してみましょう。トピック作成画面はユーザー作成画面→確認画面→(トピック作成処理)→TOP画面と遷移していきます。現行処理は確認画面にhiddenのフォームを入れることでユーザー入力画面の情報をトピック作成処理に渡すことにしていました。今回はセッションを使ってこの処理を実装してみます。

まずthread/views.pyに新しいクラスを作りましょう。以下のようなクラスを生成します。

thread/views.py

class TocicCreateViewBySession(FormView):
    template_name = 'thread/create_topic.html'
    form_class = TopicModelForm

    def post(self, request, *args, **kwargs):
        ctx = {}
        if request.POST.get('next', '') == 'back':
            if 'input_data' in self.request.session:
                input_data = self.request.session['input_data']
                form = TopicModelForm(input_data)
                ctx['form'] = form
            return render(request, self.template_name, ctx)
        elif request.POST.get('next', '') == 'create':
            if 'input_data' in request.session:
                form = self.form_class(request.session['input_data'])
                form.save()
                # Topic.objects.create_topic(
                #     title=request.session['input_data']['title'],
                #     user_name=request.session['input_data']['user_name'],
                #     category_id=request.session['input_data']['category'],
                #     message=request.session['input_data']['message']
                # )
                request.session.pop('input_data') # セッションに保管した情報の削除
                # メール送信処理は省略
                return redirect(reverse_lazy('base:top'))
        elif request.POST.get('next', '') == 'confirm':
            form = TopicModelForm(request.POST)
            if form.is_valid():
                ctx = {'form': form}
                # セッションにデータを保存
                input_data = {
                    'title': form.cleaned_data['title'],
                    'user_name': form.cleaned_data['user_name'],
                    'message': form.cleaned_data['message'],
                    'category': form.cleaned_data['category'].id,
                }
                request.session['input_data'] = input_data
                ctx['category'] = form.cleaned_data['category']
                return render(request, 'thread/confirm_topic.html', ctx)
            else:
                return render(request, self.template_name, {'form': form})

templates/thread/confirm_topic.html内でhiddenのインプットタグを削除します。

templates/thread/confirm_topic.html

{% extends 'base/base.html' %}
{% block title %}トピック作成 - {{ block.super }}{% endblock %}
{% block content %}
  <div class="ui grid stackable">
      <div class="eleven wide column">
          <div class="ui breadcrumb">
              <a href="{% url 'base:top' %}" class="section">TOP</a>
              <i class="right angle icon divider"></i>
              <a class="active section">トピック作成</a>
          </div>
          <div class="ui segment">
              <div class="content">
                  <div class="header"><h3>トピック作成</h3></div>
                  <p>内容を確認してください</p>
                  <table  class="ui celled table table table-hover" >
                      <tr><td>タイトル</td><td>{{form.title.value}}</td></tr>
                      <tr><td>お名前</td><td>{{form.user_name.value}}</td></tr>
                      <tr><td>カテゴリー</td><td>{{category}}</td></tr>
                      <tr><td>本文</td><td><pre>{{form.message.value}}</pre></td></tr>
                  </table>
                  <form class="ui form" action="{% url 'thread:create_topic' %}" method="POST">
                      {% csrf_token %}
-                     {% for field in form %}
-                         {{field.as_hidden}}
-                     {% endfor %}
                      <button class="ui button grey" type="submit" name="next" value="back">戻る</button>
                      <button class="ui button orange" type="submit" name="next" value="create">作成</button>
                  </form>
              </div>
          </div>
      </div>
      {% include 'base/sidebar.html' %}
  </div>
{% endblock %}

thread/urls.pyも変更します。

thread/urls.py

+ path('create_topic/', views.TocicCreateViewBySession.as_view(), name='create_topic'),
- path('create_topic/', views.TocicCreateView.as_view(), name='create_topic'),

これで最初に作成した確認画面付きのトピック作成画面と同等の機能をセッションを使って実装することが出来ました。セッションは基本的にはビュー内部で扱うことが多く、request.sessionに対してキーと値を持たせることで保存します。セッションエンジンにはDB,ファイル, キャッシュがありますが、今回はデフォルト設定されているDBを用いました。変更したい場合には公式ドキュメントのセッションエンジンを設定するを参考にして下さい。

セッションをビュー外部から使用することも出来ます。その場合はビューの外でセッションを使うを参考にして下さい。

おわりに

今日で30日目です。
必ずしも、毎日欠かさずやってきたわけではないですが、30日目には達しました。
私は習慣化させることが比較的に得意です。
私が大事にしていることは「小さな目標かつ、小さな設定で始めること」です。
今回の場合だと、動くWebアプリを作る(目標)、朝9:30〜11:00まで(設定)でやっています。
習慣化するには継続しなければならないので、自分ができる範囲で続けなければいけないと考えています。
自分はこれならできるという最低レベルまで下げることが、習慣化の最重要ポイントだと思っています。

それではまたまた

←前回:Day 29 Djangoでメールを送信する
→次回:Day 31 Cookieへのデータの保存と読み出し

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up