Progateで作ったWebアプリをDjangoで作ってみる! Part5 -Create編-


ProgateのNode.jsコースではお買い物リストアプリを作るのですが、これと全く同じものをDjangoで作ってみます。

Djangoでのアプリ開発の一連の流れを整理するために記していきます。

目標物

HTMLとCSS、PNG形式画像は使い回しで、一部をDjango用のタグに変えます。

前回のおさらい

Part4

お買い物アイテム一覧が表示されるListページを作成をしました。

今回は、新しい買い物リストを作成するためのNewページを作っていきます。

Newページの作成

ブラウザにデータを入力して、データベースに追加するページを作っていきます。

CreateViewという新たにレコードを追加するフォームを提供するビューを使っていきます。

まずは、HTMLファイルを作成します。

例のごとく、静的ファイル、CSSを読み込むためのタグ、index.htmlにリンクするためのurlタグをそれぞれ挿入していきます(☆1)。

☆2は重要です。Djangoはcsrf_tokenというテンプレートをformにつけることをルールとしています。

csrf_tokenはインターネット・バンキングなどにおけるワンタイムパスワードのようなイメージで、そのパスワードを持っていない状態では処理を行うことができないようになっています。

formには必ず{% csrf_token %}を入れましょう!(☆2)

☆3の部分を見ていきます。

formタグの中の{{ form.item }}の部分はDjangoのテンプレートを使った入力フォームです。データベースのitemフィールドに追加していくため、form.itemとしています(☆3)。

new.html
{% load static %} <!--☆1-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>LIST APP</title>
    <link rel="stylesheet" href="{% static 'list/style.css' %}"> <!--☆1-->
  </head>
  <body>
    <header>
      <a href="{% url 'list:top' %}" class="header-logo">LIST APP</a> <!--☆1-->
    </header>
    <div class="container">
      <div class="container-header">
        <h1>買い物リスト作成</h1>
      </div>
      <div class="item-form-wrapper">
        <p class="form-label">買うもの</p>
        <form action="" method="post">{% csrf_token %} <!--☆2-->
          {{ form.item }} <!--☆3-->
          <input type="submit" value="作成する">
        </form>
      </div>
      <a href="{% url 'list:index' %}" class="cancel-button"></span>もどる</a> <!--☆1-->
    </div>
  </body>
</html>

お決まりのviews.pyurls.pyにコードを追加していきます。

views.pyから。

おさらいをするとCreateViewは新しいレコードを追加していくフォームです。

views.pyの中でCreateViewをimportして、ListNewというclassを作成して、その中で継承します(☆4)。続いてtemplate_nameで使うHTMLファイルをnew.htmlに、使うデータベースをListModelに、データベースの中の使うフィールドをitemフィールドに設定します(☆5)。

☆6のsuccess_url = reverse_lazy()について見てみます。success_urlはフォームが正常に処理されたとき、登録されたURLにリダイレクトされます。formの「作成する」ボタンが押されると、views.pyファイルのreverse_lazyで指定したname情報が照合されます。そして、合致した場合に対応するviewを呼び出します。この場合だと、「作成する」ボタンを押すとListページ(index.html)に移ります。reverse_lazyで指定することにより、views.pyurls.pyURLという逆引き形式でURLを呼び出せます。

listapp/list/views.py
from django.shortcuts import render
from django.views.generic import TemplateView, ListView, CreateView # ☆4
from .models import ListModel 
from django.urls import reverse_lazy # ☆6

class ListTop(TemplateView):
    # top.htmlをレンダリング
    template_name = 'list/top.html'

class ListIndex(ListView):
    # index.htmlをレンダリング
    template_name = 'list/index.html'
    model = ListModel

class ListNew(CreateView):
    # new.htmlをレンダリング
    template_name = 'list/new.html' # ☆5
    model = ListModel # ☆5
    fields = ['item'] # ☆5
    success_url = reverse_lazy('list:index') # ☆6

urls.pyファイルにコードを追加して、views.pyListNewクラスを読み込むようにします(☆7)。

listapp/list/urls.py
from django.urls import path
from .views import ListTop, ListIndex, ListNew

# URLパターンを逆引きできるように名前をつける
app_name = 'list'

urlpatterns = [

    # リクエストされたパス部分が''に合致した場合、views.pyのListTopクラスをインスタンス化する
    path('', ListTop.as_view(), name='top'),

    # リクエストされたパス部分が'index'に合致した場合、views.pyのListIndexクラスをインスタンス化する
    path('index/', ListIndex.as_view(), name='index'),

    # リクエストされたパス部分が'new'に合致した場合、views.pyのListNewクラスをインスタンス化する
    path('new/', ListNew.as_view(), name='new'), # ☆7
]

Listページの修正

ListページからNewページに飛べるようにタグを加えておきます(☆8)。

index.html
{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>LIST APP</title>
    <link rel="stylesheet" href="{% static 'list/style.css' %}">
  </head>
  <body>
    <header>
      <a href="{% url 'list:top' %}" class="header-logo">LIST APP</a>
    </header>
    <div class="container">
      <div class="container-header"> 
        <h1>買い物リスト</h1>
        <a href="{% url 'list:new' %}" class="new-button">+ 新規登録</a> <!--☆8-->
      </div>
      <div class="index-table-wrapper">
        <div class="table-head">
          <span class="id-column">ID</span>
          <span>買うもの</span>
        </div>
        <ul class="table-body">
          {% for object in object_list %}
            <li>
              <div class="item-data">
                <span class="id-column">{{ forloop.counter }}</span>
                <span class="name-column">{{ object.item }}</span>
              </div>
              <div class="item-menu">
                <form action="/delete/<%= item.id %>" method="post">
                  <input type="submit" value="削除">
                </form>
                <a href="/edit/<%= item.id %>">編集</a>
              </div>
            </li>
          {% endfor %}
        </ul>
      </div>
    </div>
  </body>
</html>

これでお買い物リストにアイテムを新規作成するためのページができました。

試しに「とまと」を登録してみます。

ちゃんと登録されました!

次はリストを更新するためのページを作っていきます!

Part6に続きます!

Part6