Django初学者の自分へ（4） - メモアプリ作成 -

## **チュートリアル一覧**
| No. | タイトル                                                        |    |
|-----|:---------------------------------------------------------------|---:|
| 1   | [Django初学者の自分へ（1） - プロジェクト・アプリ -](https://qiita.com/Yi-Gaoqiao/items/c5b41d22907016ae1d0f)             |   |
| 2   | [Django初学者の自分へ（2） - MTVとは -](https://qiita.com/Yi-Gaoqiao/items/f375ea362034b8719440)                        |    |
| 3   | [Django初学者の自分へ（3） - こんにちわ世界！ -](https://qiita.com/Yi-Gaoqiao/items/e63be4937dff961c235b)                |    |
| 4   | **Django初学者の自分へ（4） - メモアプリ作成 -**                  |  ☆  |

## **前回のおさらい**
[前回](https://qiita.com/Yi-Gaoqiao/items/e63be4937dff961c235b)は Django で「こんにちわ世界！」を検証しました。
今回は **MTV** 全てを用いて、簡単なメモアプリを作成します！

## **レッツジャンゴ -メモアプリの作成-**
今回の目標はメモアプリの作成を通じて、前回使用しなかった **Model** と **Template** の理解を深めることです。また、これまで学んだことを踏まえ、Django による Web アプリ作成の一連の流れを把握できたら、この上なく嬉しいです！  

以下の流れに沿って作成していきます。
1. Model の定義
2. データベースへの反映（通例行事：migrate）
3. 管理者ページ
4. View の設定
5. Template の設定
6. URL の設定
## **Model の定義**
**Model** ではデータベースに格納するデータの定義を記述するのでした。
それでは記述していきます。

`app1/models.py`

    from django.db import models

    # Create your models here.

    class Memo(models.Model):
        title = models.CharField(verbose_name='タイトル', max_length=100)
        text = models.TextField(verbose_name='内容')
        created_date = models.DateTimeField(verbose_name='作成日', auto_now_add=True)

        def __str__(self):
            return self.title

一つ一つ見ていきましょう。

- Memo はモデルの名前です。モデルの名前は頭文字を大文字にします。
- title, text, created_date はデータベースに登録するフィールドです。
- フィールドを定義する際は、それがテキストなのか、日付なのか、はたまた数字なのか、といったフィールドのタイプを決める必要があります。
- `models.CharField` : テキストの長さを定義するフィールドです。（）内で `max_length=100` となっていますね。そうです、つまりタイトルは100文字以内で記述してくださいね、ということになります。
- `models.TextField` : これも同じくテキストですが、長さは指定しません。
- `models.DateTimeField` : これは日付と時間のフィールドです。`auto_now_add=True` としたことでデータ作成時の時刻が自動的に入力されます。
- `verbose_name` は管理画面での表示を指定します。管理画面については後述します。

以上で Model の定義は終了です。モデルのフィールドのタイプについては他にも多くの種類があるので、気になった方は[公式ドキュメント](https://docs.djangoproject.com/ja/3.0/contents/)を覗いてみてください。

## **データベースへの反映（通例行事：migrate）**
Model の定義が完了したら、それらの情報をデータベースに反映させるために**migrate（マイグレート）**という処理を行わなければなりません。これはもう通例行事というか伝統行事というか、Model の追加・変更等があった場合は必ず行わなければならないものなのです。

Model の定義からデータベースへの反映は以下の処理を実行します。

- Model の追加/変更
- マイグレーションファイルの作成（makemigrations）
- マイグレート（migrate）

#### マイグレーションファイルの作成
コマンドプロンプトで以下のコマンドを実行します。

    C:\Users\User_name\myapp>python manage.py makemigrations

すると次のような出力が確認されるかと思います。この時点でマイグレートするためのファイルは作成されたものの、未だデータベースには反映されていません。

    Migrations for 'app1':
      app1\migrations\0001_initial.py
        - Create model Memo

#### マイグレート
先ほどに続いて次のコマンドを実行します。

    C:\Users\User_name\myapp>python manage.py migrate

すると次の出力が確認されるかと思います。

    Operations to perform:
      Apply all migrations: admin, app1, auth, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying admin.0002_logentry_remove_auto_add... OK
      Applying admin.0003_logentry_add_action_flag_choices... OK
      Applying app1.0001_initial... OK
      Applying contenttypes.0002_remove_content_type_name... OK
      Applying auth.0002_alter_permission_name_max_length... OK
      Applying auth.0003_alter_user_email_max_length... OK
      Applying auth.0004_alter_user_username_opts... OK
      Applying auth.0005_alter_user_last_login_null... OK
      Applying auth.0006_require_contenttypes_0002... OK
      Applying auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying auth.0009_alter_user_last_name_max_length... OK
      Applying auth.0010_alter_group_name_max_length... OK
      Applying auth.0011_update_proxy_permissions... OK
      Applying sessions.0001_initial... OK

たったこれだけでマイグレートは完了です！
Memo モデルが無事にデータベースに反映されました！  
...とは言うものの、実際どんなことが起こったのかイメージしづらいですよね。そんな悩みを解決するために、今日はとっておきのモノをご用意いたしました。

## **管理者ページ**
Django には管理者ページがデフォルトで搭載されています。ここでは管理者ページからデータベースにデータを格納し、先ほどのマイグレートで何が起こったのか確認してみたいと思います。  

早速サーバを起動し、管理者ページにアクセスしましょう！

    C:\Users\User_name\myapp>python manage.py runserver

サーバが起動されたことを確認したら、`http://127.0.0.1:8000/admin` にアクセスします。すると以下のようなページに行きつくかと思います。
![django_admin.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641843/54f16c89-74b9-8743-51dc-457de5ce698a.png)


ん？あれ、Username に Password ？ そんなもの持ってないよ。
そうなんです、でも安心してください。これもまたコマンドプロンプトから簡単に作成できちゃいます。サーバを一度切断するか、もしくは新たなコンソールを用意し、次のコマンドを実行します。

    C:\Users\User_name\myapp>python manage.py createsuperuser
    Username (leave blank to use 'User_name'): memo_user
    Email address: memo@mail.com
    Password:
    Password (again):
    Superuser created successfully.    

上から1行ずつ表示されていきます。Username は何も入力せずに Enter を押すとあなたの 'User_name' が登録されます。メールとパスワードまで正しく入力したところでユーザー登録は完了です。もう一度サーバを起動し、先ほどの /admin ページにてログインしてみましょう。
![django_admin_page.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641843/6d91b030-1185-1917-e67a-858a0589df5e.png)
これが Django にデフォルトで搭載されている管理者ページです。シンプルで洗練されてますよね。んー、好き。
管理者ページにて Model を確認するには `app1/admin.py` にて設定してあげる必要があります。 

`app1/admin.py`

    from django.contrib import admin
    from .models import Memo          # Memo をインポート

    # Register your models here.

    admin.site.register(Memo)         # 追加

これらを記述したら、先ほどの管理者ページに戻ってページを更新してみてください。
![django_admin_add_model.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641843/b7df252a-570e-95b0-3f58-27d69a0937e6.png)
我が Memo アプリのモデルが確認できました！
それでは Memo ページに行き、右上の ADD MEMO からメモを作成してみましょう！
![add_memo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641843/2b041d0a-4d12-ee2e-6a15-7ba8aad01372.png)
皆さんはどんなメモを書きましたか？いやそんなことはどうでもよかったですね(笑)
メモのページに戻ると先ほどのメモが追加されているのが確認できるかと思います。Django ではこのように管理者ページを経由してデータベースにデータを追加したり、中身を確認することができます。どうやらこれはとんでもなく便利な機能らしく、本来ならばコンソールからデータベース言語を記述して操作したり、一から管理者ページを作成したりする必要があるんだとか。僕も正直データベースに関してはまだまだ発展途上なので、このように視覚的にデータを操作できるのは非常に助かります。  
Django、本当にありがとう。

## **View の設定**
ここからは **View** を設定していきます。View はリクエストに応じてデータベースからデータを取得し、それを画面にどのように表示するか決定するんでしたよね！

`app1/views.py`

    from django.shortcuts import render
    from .models import Memo             # Memo をインポート

    # Create your views here.

    def memo_list(request):
        memos = Memo.objects.all()

        context = {'memos': memos}
        return render(request, 'app1/memo_list.html', context)

今回はメモの一覧を画面に表示させるようにします。そのためには Memo のモデルのデータを取得する必要があります。

- `memos = Memo.objects.all()` : Memo の持つすべてのオブジェクト（タイトル、内容、作成日）を取得します。
- `context = {'memos': memos}` : 必要な情報を辞書型にして Template に渡します。
- `render(request, 'app1/memo_list.html', context)` : `context` を `app1/memo_list.html` に渡します。ここで言う `memo_list.html` が Template です。（`memo_list.html` はこの後作成します）

View の設定は以上です。データを取得する際には条件を絞ったりすることも可能ですが、今回はシンプルイズベストで全て取得しちゃいます。データの取得方法も[公式ドキュメント](https://docs.djangoproject.com/ja/3.0/contents/)が参考になると思います。
## **Template の設定**
いよいよ大詰めです。Template はデフォルトで用意されていないので自分で用意する必要があります。アプリ配下に templates というディレクトリを用意し、その中にさらに app1 というディレクトリを用意します。そして app1 の中に html ファイルを納めます。なぜこのような構図にするかということに関しては、naritoブログさんの[こちらの記事](https://narito.ninja/blog/detail/135/)が参考になりますので、ご参照ください。

`myapp/templates/app1/memo_list.html`

    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Memo</title>
    </head>

    <style>
        .app-name {
            text-align: center;
        }
        .contents {
            margin-left: 300px;
            margin-right: 300px;
        }
    </style>


    <div class='app-name'>
        <h1><a href="">ぼく・わたしのメモ</a></h1>
    </div>

    <!-- メモの内容 -->
    {% for memo in memos %}
    <div class='contents'>
        <hr>
        <h2>タイトル : {{ memo.title }}</h2>
        <p>作成日 : {{ memo.created_date }}</p>
        <p>{{ memo.text | linebreaks }}</p>
    </div>
    {% endfor %}
    </html>


ここでは HTML/CSS については触れず、先ほどの View から受け取った memos を如何に Template に表示させるかにフォーカスします。

- if, for 構文は {% %} で囲います。
- `memo.title` はメモのタイトルを、`memo.created_date` はメモの作成日を、`memo.text` はメモの内容をそれぞれ取得します。これらのデータを表示させるには {{ }} で囲う必要があります。
- `linebreaks` は `text` 内の改行を適宜 HTML タグに変換してくれます。

ここまで来たらゴールはもうすぐそこです！
残すは URL の設定だけです！

## **URL の設定**
`memo_list/` という URL を設定し、`views.memo_list` に処理を振り分けるようにします。
`app1/urls.py`

    from django.urls import path
    from . import views

    urlpatterns = [
        path('', views.hello),
        path('memo_list/', views.memo_list),    # 追加
    ]

それではいつものようにサーバを起動し、`http://127.0.0.1:8000/memo_list` にアクセスしましょう！
![memo_app.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641843/caa8095d-4828-6641-9d81-a14c1cfac368.png)
遂にやりましたね！
**Model** - **Template** - **View** がしっかりと手を取り合い、メモアプリを完成させることができました！おめでとうございます！
もちろんこれは初歩中の初歩中の初歩に過ぎませんし、物足りないと感じるのも無理はありません。
メモアプリといえば、

- 投稿・編集・削除
- 一覧表示
- 詳細表示
- 検索  
... 

といった機能があるともっと便利ですよね。安心してください、今ここにあげたものは全て Django で実装できてしまうのです！ほら、Django のこともっと知りたくなったでしょ？さらに HTML/CSS を学んで装飾してあげれば、デザインにも富んだWebアプリケーションを作成できるのです！

## **最後に**
さて、いかがだったでしょうか。この度は僭越ながら計4回に渡って Django のチュートリアルを書かせていただきました。本チュートリアルの目標である「 Django の仕組みを超絶ざっくりと理解し、Djangoって怖くないんだよ、面白いんだよ、と感じてもらう 」は達成していただけたのではないでしょうか。  
学習開始当初の僕もきっと「Django 怖くない！面白い！」って言ってるはず。

## **参考文献**
- [公式ドキュメント](https://docs.djangoproject.com/ja/3.0/contents/)
- [Django Girls Tutorial（日本語）](https://tutorial.djangogirls.org/ja/)
- [naritoブログ](https://narito.ninja/blog/)
- [Teckpit](https://www.techpit.jp/p/django-trello)
- [code for django](https://codor.co.jp/django/)
- [Dennis Ivy](https://www.youtube.com/channel/UCTZRcDjjkVajGL6wd76UnGg/featured) (Youtube)