Django 初心者が簡単なアプリをつくる1

## はじめに

Djangoを学び始めて1年半。ようやく自分自身の手で簡単なWebアプリ(もどき)を作ることができたので復習がてら記録しておく。永遠の初心者Programmerがつかんだわずかばかりの知見を共有して、初手でつまづいている人たちのお役に立てればこれ幸い。

### 目的

複雑なことや面倒なことを極力削ぎ落として、単純化したWebアプリを作り、Djangoの仕組みを学ぶことに特化する。よってDjangoチュートリアルその5のようなテストもしない、CSSも使わない、デプロイもしない。いわゆるフロントエンドはひとまず横に置く。バックエンド中心に何がどう繋がり動くのかだけを理解する。ひと通りCRUD(Create, Read, Update, Delete)を実装し、無事動けばゴール。（ネットに繋がないのにWebアプリ？というツッコミはナシでお願いします。）

### 対象

DjangoチュートリアルやDjangoGirlsをひと通り終えたものの、何がどうなっているのかわかったようでわからない、これで自力でWebアプリを作ることなんか無理ゲーと思う人

### 初心者が簡単なアプリをつくるシリーズ目次
- [Django 初心者が簡単なアプリをつくる1](https://qiita.com/soh506/items/4035650d2ea19e82d8fd)
    - 準備・Djangoの全体像・models.pyの作成
- [Django 初心者が簡単なアプリをつくる2](https://qiita.com/soh506/items/98239c6b1c6fbf737429)
    - Read部分の実装（urls.py・views.py・templateファイルの作成）
- [Django 初心者が簡単なアプリをつくる3](https://qiita.com/soh506/items/34cef1d386e1aa1b4496)
    - Create部分の実装（form.py等の作成)
- Django [初心者が簡単なアプリをつくる4](https://qiita.com/soh506/items/ac9b2914f64839edac3b)
    - Class-based-view と Function-view の比較
- Django [初心者が簡単なアプリをつくる5](https://qiita.com/soh506/items/fc6b00ba728ac41fa3d1)（完結）
    - Update部分・Delete部分の実装


### 環境

- Ubuntu 20.04 LTS
- Python 3.8.2
- Django 3.02

## Djangoの全体像

「DjangoはPythonを使ったWebアプリケーションフレームワークだ」とよく書かれているもののピンとこない。自分なりに理解したところでは、Webアプリって何？と聞かれれれば「DB(データベース)から情報(あるいはデータ)を取り出し表示するもの」と答えるし、じゃあフレームワークって何？と聞かれれば、「その作業（情報を取り出し表示する）を楽にするために色んな道具がつまった道具箱」と答える。

### Djangoの内部でどんなことをやっているか

Djangoが内部でやってることをイメージすると下図の感じ。情報が詰まっている箱から情報を取り出して掲示板に貼ってる。

<img width="839" alt="IMG_0354.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/b3f4baab-e394-e5c8-1663-8fbbf21170b6.jpeg">


1. models.py : 情報の入れ物を作る
2. urls.py : 情報を表示する場所（どの掲示板に貼るか）を決める
3. views.py : 情報をどう集めて処理をするか決める
4. Template : 情報をどうやって貼り出すかを決める

上記4つのファイルを順番に作ったり変更したりすれば最低限動くようになる。

## 0. 準備をする（ロケット発射のページまで）

チュートリアルをやった方ならばDjangoが動くまではいけるはず。以下のリンクはご参考までに。

[Django を VSCode で 開発するまでの手順](https://qiita.com/soh506/items/12a5df2d19f1c2c792fe)

## 1. 準備をする（全体の設定を完了する)

ロケット発射のページの表示後、仮想環境からアプリを作成するコマンドを入力。今回のアプリ名はmyappとする

```
(myenv)$ python manage.py startapp myapp
```

次にconfig/setting.py を修正する

- INSTALLED_APPS に `myapp` を追加
<img width="1321" alt="IMG_0358.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/f22fa5c9-4b24-b1d0-425d-74eae468a385.jpeg">

- TEMPLATES に `[os.path.join(BASE_DIR, 'templates')],`を追加
<img width="1328" alt="IMG_0359.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/1418f0d3-a382-d00a-eacb-035589a65d0b.jpeg">

- LANGUAGE を `ja` に修正
- TIME_ZONE を `Asia/Tokyo` に修正
- STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]を追加
<img width="1324" alt="IMG_0360.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/3e14b40f-2318-a2c0-dfea-896d82c409c9.jpeg">

- templates ディレクトリを manage.py と同じ階層に作成
- static ディレクトリを manage.py と同じ階層に作成

以下のディレクトリ構成・ファイル構成（主なものだけ抜粋）になるはず。

```
.
├── config    #configにしたのは「現場で使えるDjangoの教科書基礎編」を参考にした
│   ├── settings.py
│   ├── urls.py
├── db.sqlite3
├── myenv
│   ├── bin
│   ├── include
├── manage.py
├── myapp
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── static   　　　　 #staticディレクトリとtemplatesディレクトリの置き場所はチュートリアルによって
└── templates        #違ったりするがmanage.pyと同じ階層がいいらしい

```

以上ですべての準備段階が完了。


## 2. 設計をする
ゴール設定をすると。つくるWebアプリは「映画視聴記録」。自分が観た映画のリストが一覧に出て、タイトルをクリックするとその映画の感想が出てくる。Yahoo映画のむっちゃ簡易バージョン。このCRUD(Create, Read, Update, Delete)を実装できたらゴール。このゴールを決めておかないと、こだわり始めたら際限なくて、難しい機能や美しい見た目や使い勝手まで追求し始めると、あまりもの目標の遠さに心が折れてしまうのです。以下ができあがりのぼんやりとしたイメージ。

<img width="1030" alt="136231D5-13EE-474C-9135-D306B8C5A305.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/06c061e6-57d1-1aa6-5727-863857edc789.jpeg">

これに以下の機能が実装できればいいわけで。

1. 映画視聴一覧が出てくる (Read)
2. タイトルクリックしたら詳細画面が出てくる (Read)
3. 映画のタイトル、映画監督、視聴日、感想を入力する (Create)
4. 入力した感想を修正する (Update)
5. 映画があまりにもひどかったので情報を消して観なかったことにする (delete)

まずは情報を入れる箱づくり ＝ modelを作る作業に入りたい。

## 3. models.py を作る

modelを作るというのは「情報を入れる箱づくり」と先程書いたが、別の言葉でいうと「表づくり」かなと。小さな表をいくつか作ってそれらを「ひもづけ」して大きな一覧表を作るイメージ。今回はMovieという表と、Directorという表と、Logという表を作る。ソースコードは以下の通り。

```python:myapp/models.py

from django.db import models #表をつくるための道具を持ってくる
from django.utils import timezone #時間を扱うための道具を持ってくる


class Director(models.Model): #Directorという表を作る
    name = models.CharField(max_length=100, verbose_name="監督") #nameというfieldに文字列で監督名を入れる宣言
    def __str__(self): #以下2行は管理サイト使ってデータ入力したときに監督の名前で表示するための関数
        return self.name


class Movie(models.Model): #Movieという表をつくる
    title = models.CharField(max_length=100, verbose_name="タイトル")
    watch_date = models.DateField() #timezoneという道具を持ってきたので、日付のデータを入力できる
    director = models.ForeignKey(Director, on_delete=models.CASCADE, verbose_name="監督", related_name='movie')
    def __str__(self):            #directorっていうfieldは「Directorという表」から紐付けして持ってきますよという宣言
        return self.title         #related_nameに関しては別の回で詳しく説明予定


class Log(models.Model): #Logという表をつくる
    text = models.TextField() #textというfieldにはたくさん文字列を入力するための場所ですよという宣言
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE, verbose_name="タイトル", related_name='log')
    def __str__(self):            #movieっていうfieldは「Movieという表」から紐付けして持ってきますよという宣言
        return self.text          #self.textで管理サイトを使ってデータ入力したときに入力した内容で表示される

```

上記のソースコードで下図のようなものができるとイメージする。
<img width="1332" alt="B594169D-3FD9-4CB6-ACD9-756DDE66F7D2.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/c22e3589-ff84-8346-6932-a8193454d5d5.jpeg">


models.py ができたらこれは設計図なので実際にデータベースに反映させる

```bash
(myenv) $ python manage.py makemigrations
(myenv) $ python manage.py migrate
```
表はできあがったが、中身（データ）がない。データを入力するのに`python manage.py shell`から入力することもできるが、管理サイトからデータを入力するほうが簡単だしイメージしやすい。管理サイトを利用するために admin.py に model を登録する

```python:myapp/admin.py

from django.contrib import admin
from myapp.models import Director, Movie, Log    #この部分を追加

admin.site.register(Director)    #もしかするとまとめて登録するやり方があるのかもしれない
admin.site.register(Movie)       #どなたかご教授していただけると助かります
admin.site.register(Log)
```
管理サイトを使用するためのsuperuserを設定する

```bash
(myenv) $ python manage.py createsuperuser
#ユーザー名・メールアドレス・パスワード等を設定する
```
管理サイト(127.0.0.1:8000/admin)から何個かデータを入力する
<img width="1300" alt="F4284CE1-80D6-42AD-8935-8E8DA27B2C54.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/95003006-88fb-5ec8-724b-3428040d309b.jpeg">

models.py も出来上がり、データも入力したので、これで第1段階終了。次回は urls.py でどこに表示するか、views.py でどうやって情報を取り出すか、Template を作成しどうやってその情報を表示するのか、までを説明する予定。

## まとめ
- Django はデータベースに貯めた情報を取り出して表示する、その作業を楽にしてくれる
- まずは情報を貯める models.py を作る
- model とは表であり、どんな項目を表示する表にするのか、入れるデータの型は何か、紐付けをどうするかを考える

次回　[Django 初心者が簡単なアプリをつくる2](https://qiita.com/soh506/items/98239c6b1c6fbf737429)　へ続く