未経験でもToDoリストくらいなら作れるよ、Djangoならね

# はじめに
今回の記事では、駆け出しエンジニアの私が Django で ToDoリストを作った際、
実際に作成した手順と、作成して得た学びについて話していきたいと思います。

この記事では ToDoリストを形にする手順というより、
私が実際作成する際、**どのようなことを感じたか**
について、時系列に沿ってお伝えしたいと思っています。

私と同じ初学者の方にはこの記事を読んで、
**『こいつも頑張っているから私も頑張ろう』**
と思っていただけると嬉しいです。

また、後輩にエンジニア未経験がいる方には、
**『未経験ってこんな感じなんだ』**
と実態を把握していただけると嬉しいです。


# ToDoリストを Django で作成した流れ
私が実際 ToDoリストを形にした流れは以下の通りです。
1.  **Django チュートリアルで Django に触ってみた**
1. **チュートリアルで作成したアプリをもとに ToDoリスト作成を試みた**
1. **一度作業を白紙に戻して、先人が作成した ToDoリストを参考にして作成した**
1. **機能を追加してみた**

以上の流れでお話を進めていきたいと思います。
この作業の中で私が思ったこと、感じたことについても随所でお話しできればと思います。

## 1. Django チュートリアル 
まずはじめに、Django とは一体何なのかを知るために、
チュートリアルで手を動かしながら理解していくことを試みました。

* チュートリアルで参考にしたサイトは以下のものです。

https://docs.djangoproject.com/ja/4.2/intro/

手順に沿って作成し、私は[はじめての Django アプリ作成、その 5](https://docs.djangoproject.com/ja/4.2/intro/tutorial05/) まで取り組みました。
***
その１〜５で学習できる内容について簡単に共有させていただきたいと思います。
* [その1](https://docs.djangoproject.com/ja/4.2/intro/tutorial01/)
  * プロジェクトとアプリケーションの作成
  * ビューの作成とurlパスの指定
* [その2](https://docs.djangoproject.com/ja/4.2/intro/tutorial02/)
  * データベースの設定
  * モデルの作成、設定
  *  Django の API を python で触ってみる
  *  管理者の設定
* [その3](https://docs.djangoproject.com/ja/4.2/intro/tutorial03/)
  * 実際に動作するビューの作成
  * テンプレートシステムの利用
* [その4](https://docs.djangoproject.com/ja/4.2/intro/tutorial04/)
  * フォームの作成
  * 汎用ビューの活用
* [その5](https://docs.djangoproject.com/ja/4.2/intro/tutorial05/)
  * 自動テストの作成・実行
***

一通りチュートリアルを経験してみることで
* Django とはどのようなツールなのか
* Django を使うとどんなメリットがあるのか

といったような、大まかな理解ができます。
初めてプログラムを見るよという方は少し抵抗感を感じるかもしれないです。
ただ、とりあえずやってみて何となく理解するということは大事だと思いますので、ぜひ頑張ってみてください。

この段階で、Django の MVTモデル(Model-View-templatesの関係性)のイメージを明確に理解できるともっと良いと思います。私はそこの理解が曖昧なまま進んでしまって、のちの ToDoリスト作成がだいぶ困難でした。

## 2.作成したアプリをもとに ToDoリスト作成
チュートリアルを一通り終えると、**polls** という投票アプリが作成できると思います。
私はその投票アプリを ToDoリストへ修正しようと試みました。

具体的な作成したかったイメージは、以下のようなモノです。
* 投票する際のチェックボックスの動作を ToDoリストに活用する
* チェックリストの下に ToDoを追加するフォームを作成する

しかし、自分のイメージを実際にプログラムに落とし込むために、
どのようなコードをどこのファイルに記入しなければならないのかがさっぱりわかりませんでした。

まず、私は **polls** の中身の、`views.py` `models.py` `detail.html` あたりをいじってみました。
検索をかけて参考になりそうなコードを、それっぽいファイルに追加して......

結局、丸一日かけて成果物は何も残りませんでした。

### 状況の打開

その後私は、会社の先輩に時間を作っていただき相談しました。
相談の中で学んだことについて共有したいと思います。
私と同じくプログラミングがほとんどわからない方にぜひ参考にしていただきたいです。

相談して教示していただいた内容は、以下の 3 点です。
#### (Ⅰ) 着手すべきポイントを切り分けるべき
 私は ToDoリストを作成するにあたって、変更を加えると考えられるファイルを闇雲に編集していました。

しかしそうではなく、変更を正しく反映させるために着手するポイントを切り分けて考える必要があります。ポイントを切り分けて段階的に構築することが、イメージしたものをプログラムする基本となります。

また、ポイントの切り分けはエラーの対処の際も必要です。
エラーに対処する際、問題を切り分けることで効率的に問題を特定し、迅速に解決することができます。

以上の理由から、着手すべきポイントを切り分ける事が必要になります。

#### (Ⅱ) わからないものにわからないまま突っ込んではいけない

プログラムを作成する際、自分が作成したコードを読んで正しく理解する必要があります。
そのため、コードの中身を細かく読み、コードの中にわからない動作があった際は詳細に調べて完璧に理解することが必須となります。

私は機能の変更を加える際、様々なサイトを参考にし、コードを何となく追加していました。
しかしプログラムはそれぞれのアプリが動作するように作成されており、そのままコードを引っ張ってきて記述するだけでは動作しません。

そのため、自分の手元のコードを正しく理解した上でサイトを参考にし、プログラムの考え方を参考にする、という方法が良いと考えています。

#### (Ⅲ) 差分を見ていく
プログラムを理解するために、実際に動作する ToDoリストを一から作成し、それと変更したいプログラムを比較して違いを発見していく、ということです。

一から作成したToDoリストのプログラムを正しく理解し、それを **polls** で記述するために、どの箇所をどう編集すべきかを考えます。

そうすることで MVTモデルの流れを把握し、プログラムとして記述する際も相互の関連性を意識して構築できます。

#### 相談を通して

MVTそれぞれの関係性を十分に理解しきれていなかった点に問題点があったことを自覚し、
また次に意識すべきことが明確になりました。

**polls**をToDoリストにするという当初の目標は果たせなかったですが、
意識することがわかったところで、
次に一度作業を白紙に戻し、簡単なToDoリストを一度作成してみることにします。

## 3. 先人が作成した ToDoリストを参考にして作成

再構築するにあたって、ToDoリストを Djangoで作成している記事を参考にしました。

私が参考にしたのは、[kenpapa](https://note.com/kenpapa/) さんの [DjangoでTodoアプリを作ってみよう](https://note.com/kenpapa/n/nee12a3ea8d00)という記事です。初心者でもわかりやすい内容だったため、ご参考にさせて頂きました。

https://note.com/kenpapa/n/nee12a3ea8d00

この記事の手順に従って作業を進め、まず ToDoリストを形に残しました。
その後、コードを読んで差分を見てみてMVTモデルの関連性を体感して理解することで、
だんだん流れを意識しながらプログラムを組めるようになってくると思います。

## 4. 機能を追加してみる

最後にこの ToDoリストに独自の機能を追加してみます。

実際に手を動かしてやってみることが効率的な理解につながると考えています。
もしこの記事をここまで読んでくださった方がいらっしゃれば、ぜひお好きな機能を試しに追加してみてください。

では機能の追加についての手順を以下に書いていきたいと思います。

### 機能の追加手順

まず、私が追加しようと考えた機能は、**期限を ToDoリストに加えて記載できる機能**です。
早速、実際のコードをどのように書いていくのかについてお伝えしたいと思います。

機能を書き加えていくものは、以下の 3 つのファイルです。
* `models.py`
* `views.py`
* `index.html`

この 3 つは下図のような関係性で関連付いています。
![スクリーンショット 2023-08-23 17.18.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537130/473fe2c4-b028-7f40-ddde-a9863806b4b6.png)



#### (ⅰ) `models.py`の編集

はじめに、`models.py`に必要なコードを書き加えていきます。
現在の中身としては以下のような記述がされていると思います。
~~~ruby:models.py
from django.db import models

class Todo(models.Model):
   text = models.CharField(max_length=100)
~~~

こちらの ToDoのモデルのフィールドには、
`text`という文字列のフィールドしか存在していないことが見て取れます。

期限を表示するためには、その期限を格納するフィールドも定義する必要があります。
そのため、ToDoクラスの中に、以下のコードを書き加えていきます。
~~~ruby:models.py
deadline = models.DateField(auto_now=False)
~~~
よって、`models.py`の中身は
~~~ruby:models.py
from django.db import models

class Todo(models.Model):
   text = models.CharField(max_length=100)
   deadline = models.DateField(auto_now=False)
~~~
といったようになります。

コードの中の`DateField`は日付を保存する規定のフィールドです。
また、`auto_now=False`は、`auto_now`というオブジェクトが保存される度に自動的に現在時刻に更新される機能を消しています。

デフォルトでは`auto_now=True`なのですが、期限設定時に毎回現在時刻に設定されてしまうエラーが起きてしまうため、`False`としています。

以上で`models.py`の編集は完了です。
モデルを変更したため、
`python manage.py makemigrations`
`python manage.py migrate`
を順に行い、すべて完了です。

#### (ⅱ) `views.py`の編集

次に、`views.py`に必要な機能を追記していきます。
このファイルの中身に以下のような記述があると思います。
~~~ruby:views.py
def addTodo(request):
   todo = Todo(text=request.POST['text'])
   todo.save()
   return redirect('/todos')
~~~
この`addTodo`メソッドに、期限設定の追加機能を記述していきます。
実際のコードは以下の通りです。
~~~ruby:views.py
def addTodo(request):
   todo = Todo(text=request.POST['text'], deadline=request.POST['deadline'])
   todo.save()
   return redirect('/todos')
~~~
上記のコードで、ToDoリストを追加するメソッドに、期限を設定する機能を追加しています。
ユーザーが設定した期限を`deadline`という変数に格納し、それを`todo`というオブジェクトに格納します。`todo`オブジェクトの中身には、`text`と`deadline`が入っている状態になります。

`views.py`の記述についても以上になります。
次に、画面表示の`index.html`に追記していきます。

#### (ⅲ) `index.html`の編集

次に、`index.html`に必要な情報を追記していきます。
現在、このファイルには以下のような記述がなされていると思います。
~~~:index.html
<form action="/todos/add" method="POST">
   {% csrf_token %}
   <input name="text" placeholder="Input here...">
   <button type="submit">ADD</button>
 </form>
~~~
この、フォームの内容が書かれたコードに追記していきます。
追記したい内容は期限を設定できる項目のため、以下のように記述します。
~~~:index.html
<form action="/todos/add" method="POST">
   {% csrf_token %}
   <p><input name="text" placeholder="Input here..."></p>
   <p><input name="deadline" type="date" ></p>
   <button type="submit">ADD</button>
 </form>
~~~
`<p>`という記述は改行したかっただけなので気にしないでください。

ここで追記したものは`<input name="deadline" type="date" >`です。
`type="date"`はユーザーに日付を入力させる入力欄を、検証付きのテキストボックスまたは特殊な日付選択インターフェイスのどちらかで生成するものです。([mdn web docs](https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/date))

以上でフォームの準備は整いました。
次に、フォーム送信後の結果の表示について追記します。
現在、以下のような記述がされていると思います。
~~~:index.html
<ul>
   {% for todo in todos %}
   <li>
     {{ todo.text }}
     <form action="/todos/delete/{{ todo.id }}"
           style="display: inline;" 
           method="POST">
       {% csrf_token %}
       <button type="submit">DEL</button>
     </form>
   </li>
   {% endfor %}
 </ul>
~~~
表示したいのは期限のみなので、`{{ todo.deadline }}`と追記します。
以下の通りのコードになります。
~~~:index.html
{% for todo in todos %}
   <li>
     {{ todo.text }}
     {{ todo.deadline }}
     <form action="/todos/delete/{{ todo.id }}"
           style="display: inline;" 
           method="POST">
       {% csrf_token %}
       <button type="submit">DEL</button>
     </form>
   </li>
   {% endfor %}
~~~
これで、ToDoのテキストの横に期限も表示されるようになったと思います。

機能の追加手順は以上ですべて完了です。

### 完成図

* ⇩初期画面⇩
![スクリーンショット 2023-08-23 15.27.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537130/a100b289-398e-1fbd-136c-a72405a43c30.png)

* ⇩リストに文言の追加/日付の選択⇩
![スクリーンショット 2023-08-23 15.48.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537130/29d082cd-1789-8715-a895-a946a017aafd.png)

* ⇩実行結果⇩
![スクリーンショット 2023-08-23 15.56.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537130/5cc6428b-ba9d-3633-d697-7dd42c962739.png)

見栄えは若干アレですが、モノはできましたね。

# まとめ
今回、私が ToDoリストを作成したとき経験したことについてお伝えさせて頂きました。
これからも初学者なりにもがいて、エンジニアと自信を持って言えるようになりたいと思います。
みなさん、一緒に頑張りましょう。