Progateで作ったWebアプリをDjangoで作ってみる！ Part6 -Update編-

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

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

**目標物**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/16123e6f-f050-226e-a369-8383267de571.png)


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

#前回のおさらい

[Part5](https://qiita.com/insilicomab/items/2fed2ab28abb538a9683)

Part5では、新しい買い物リストを作成するためのページを作りました。

今回はお買い物アイテムを編集・更新するEditページを作成していきます。

#Editページの作成

EditページはPart5で作ったNewページとほとんど同じです。

```html:edit.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>
      </div>
      <div class="item-form-wrapper">
        <p class="form-label">買うもの</p>
        <form action="" method="post">{% csrf_token %}
          {{ form.item }}
          <input type="submit" value="更新する">
        </form>
      </div>
      <a href="{% url 'list:index' %}" class="cancel-button">もどる</a>
    </div>
  </body>
</html>
```

データの編集・更新をブラウザ上でできるようにするため、**UpdateView**というビューを作成します。

基本的にcreateをupdateに変更する以外は、Part5でやった**CreateView**と同じです（☆1）。

[Part5](https://qiita.com/insilicomab/items/2fed2ab28abb538a9683)

```python:listapp/list/views.py
from django.shortcuts import render
from django.views.generic import TemplateView, ListView, CreateView, UpdateView # ☆1
from .models import ListModel 
from django.urls import reverse_lazy

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'
    model = ListModel
    fields = ['item']
    success_url = reverse_lazy('list:index')

class ListEdit(UpdateView): # ☆1
    # edit.htmlをレンダリング
    template_name = 'list/edit.html' # ☆1
    model = ListModel # ☆1
    fields = ['item'] # ☆1
    success_url = reverse_lazy('list:index') # ☆1
```

いつも通り、**urls.py**ファイルにコードを追加して、**views.py**の**ListNew**クラスを読み込むようにします（☆2）。

若干違うのは、``'edit/<int:pk>'``の部分です。この``<int:pk>``が、テーブルに入っているデータを具体的に指定する上で使われるコードです。pkというのはprimary keyの略で、データベースがデータを特定するときに使われる項目のことです。つまり、この場合だと、選択したお買い物アイテムに固有のもので、選択したアイテムを編集・更新できるように個別のEditページが表示されます。

```python:listapp/list/urls.py
from django.urls import path
from .views import ListTop, ListIndex, ListNew, ListEdit

# 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'),

    # リクエストされたパス部分が'edit/pk'に合致した場合、views.pyのListEditクラスをインスタンス化する
    path('edit/<int:pk>', ListEdit.as_view(), name='edit'), # ☆2
]
```

#Listページの修正

primary keyで選択したアイテムを指定した個別のEditページに飛ぶようにします（☆3）。

```html: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>
      </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="{% url 'list:edit' object.pk %}">編集</a> <!--☆3-->
              </div>
            </li>
          {% endfor %}
        </ul>
      </div>
    </div>
  </body>
</html>
```

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

試しに、リストの中の「にんじん」を「たまねぎ」にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/3084ce02-5a0d-6677-4d85-b41bf95dc2c9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/376f905a-7b33-9acb-e5d5-12b60dde53e2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/0a715931-9bd7-f69a-43f0-bcc3d3ae7aaf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/9653f9f6-43af-578b-af6b-f7877872d419.png)

ちゃんと「たまねぎ」に編集することができました！

次は、リストを削除するためのページを作っていきます！

Part7に続きます！

[Part7](https://qiita.com/insilicomab/items/6179976daa7b922a19a6)