初めてのDjango ~Python編~

# Django（ジャンゴ）とは
Djangoとは、PythonでWebアプリを開発する際に使う「**Webフレームワーク**」です。

Webフレームワークとは、簡単に言うと「**Webアプリ開発をする際に、開発効率を上げるための便利な機能がたくさん詰まったツール**」です。

身近なもので例えると、料理をすべて独学でやろうとすると火加減が大変だったりしますが、電子レンジというフレームワークを使えばワンタッチで簡単にできる、というようなイメージを持ってもらえればと思います。
※あくまでイメージです。

Djangoを使えば高品質なWebアプリケーションを簡単に少ないコードで作成できます。
シンプルなものであれば、数分で作れてしまうかも…

#### Djangoで作られている有名なサイト一例
・YouTube
・Instagram
・The New York Times
・NASA Official Website

# PythonにおけるDjangoの特徴
### ①標準的な機能が含まれている
Webアプリ開発でよく使われる、**ユーザー認証**や**管理画面**、**サイト案内のぺージ**など、よく使われる機能が標準で含まれています。
### ②セキュリティ
あらゆる脅威に対して対策がされてます。
### ③高い拡張性と柔軟性
Djangoで扱う各ファイルは役割が決まっており、**別々に切り分けて開発を行うことができる**ため、それぞれ部品の独立性が高く簡単に拡張することができます。そのため、あらゆる規模のWEBアプリでも、柔軟に対応できます。
### ④豊富な用途
先ほど述べたように、Djangoは会社や組織、そして政府にも利用されており、管理システムやソーシャルネットワーク、科学技術計算など幅広い用途に対応しています。

# Djangoのインストール
※ここから先はVScodeを利用してる前提で記載します。

まず、ターミナルにて
```.tst:ターミナル
pip install django
```

と入力すると、ダウンロードされます。
これでDjangoのインストールができました。　

# プロジェクトの作成
ではまず最初に新規プロジェクトを作成してみましょう。

今回は次のようなチャットアプリを作成してみます。
#### 「CHAT APP」
機能
・上から新しい情報
・Todoリスト
・登録、更新日時の表示

[完成品のソースコード](https://github.com/endeavort/django-chatapp)
 

プロジェクト名をchat_appとして作成します。
```.tst:ターミナル
python3.10 -m django startproject chat_app
"pythonバージョン名" -m django startproject "プロジェクト名"
```

成功すると次のようなフォルダ構成になると思います。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/15dad125-2d01-a623-3685-78ceff6703e4.png)

各ファイルの役割は次のようになります。
※初心者用にざっくりとした簡単な説明なので、あくまでイメージです。

###### ・_init\_.py：Pythonのパッケージを示すファイル
このファイルを作ることで、これがあるフォルダをパッケージ化することができ、
他のファイルにあるモジュールを簡単に利用することができます。

###### ・settings.py：Djangoプロジェクトの設定ファイル
Webアプリケーションにおけるプロジェクトの設定を記述するファイルです。
この設定値でWebアプリケーションの様々な設定や動作が変わります。

###### ・urls.py：プロジェクトのURL宣言ファイル
どのURLを実行するとどの処理が実行されるのかを記述するファイルです。

###### ・wsgi.py：デプロイ用ファイル
WSGIとはWeb Server Gateway Interfaceの略で、pythonにおいてWebサーバとWebアプリケーションが通信するための
標準化されたインタフェース定義です。Webサーバに接続する際に読み込まれる設定を記述するファイルです。

###### ・asgi.py：デプロイ用ファイル
ASGIとはAsynchronous Server Gateway Interfaceの略で、非同期でアプリケーションを実行する様のインタフェース定義です。
Django3で導入され、wsgi同様、Webサーバに接続する際に読み込まれる設定を記述するファイルです。

###### ・manage.py：Djangoのコマンドを実行する時のファイル
プロジェクトに対する様々な操作を行うためのファイルです｡

# アプリケーションの作成
続いて先ほど作成したプロジェクトファイル、manage.pyと同じ階層にアプリケーションを作成します。
アプリケーション名をtodo_appとして作成します。
```.tst:ターミナル
python3.10 -m django startapp todo_app
"pythonバージョン名" -m django startapp "アプリケーション名"
```
成功すると次のようなフォルダ構成になると思います。![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/f8e266af-0aba-59c4-8ecf-8223b68158b0.png)
各ファイルの役割は次のようになります。
###### ・_init\_.py：Pythonのパッケージを示すファイル
###### ・migrations：マイグレーションファイルを格納するフォルダ
データベースを生成する際の設計図になるものです。
###### ・admin.py：管理サイトの設定ファイル
管理者（Administrator）や開発者が利用します。
管理サイトを通して、簡単にテーブルのレコードを操作することが可能です。
###### ・apps.py：アプリケーションを構成するための設定を記述するファイル
appの設定を記述することでその内容をsettings.pyで読み込めるようにし、
プロジェクト全体に該当するappの機能を反映しています。
###### ・models.py：モデル定義時に利用するファイル
データベースに登録するテーブルを記述していきます。
###### ・tests.py：テストコードを記述するファイル
Djangoのもつテスト機能をこのtests.pyを使用して行うことができます。
###### ・views.py：DjangoのViewを定義するファイル
プロジェクトの中核を担うファイルです。このファイルを通じてこのファイルを通じて各種機能を読み込んだり、
htmlファイルの設定やデータの登録など、バックエンドとしての機能を持たせることができます。

# アプリケーションの紐付け
まず先ほど作成したアプリケーションをsettings.pyに紐付けします。
settings.pyを開き、INSTALLED_APPSのリスト内に'todo_app'を追加します。
```.tst:settings.py
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "todo_app",  # アプリケーション名
]
```
続いて言語とタイムゾーンの設定を変更します。
```.tst:settings.py
LANGUAGE_CODE = "ja"  # 日本語

TIME_ZONE = "Asia/Tokyo"  # 日本時間
```

# データベース
### ①初期設定
データベースの初期値を作成します。
```.tst:ターミナル
python3　manage.py migrate
```
データベースが作成されました。
![スクリーンショット 2023-02-26 13.55.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/f810e7fe-909c-b8a0-ff01-395be4d0edda.png)

### ②テーブルの作成
続いてテーブルを作成していきます。
todo_appフォルダ内にあるmodels.pyファイルを開き、以下の記述を行います。
```.tst:models.py
# Create your models here.
class Todo(models.Model):
    memo = models.TextField()  # todoの内容を保持するフィールド（テキスト）
    is_done = models.BooleanField(default=False)  # 処理済みかどうかを管理(True or False)
    created_at = models.DateTimeField(auto_now_add=True)  # 作成日時を保持(日付型)
    updated_at = models.DateTimeField(auto_now=True)  # 更新日時を保持（日付型）
```

### ③モデルの作成
先ほど作成したTodoクラスを利用して、モデルを作成します。
```.tst:ターミナル
python3 manage.py makemigrations todo_app
```
次の様に表示されれば成功です。
![スクリーンショット 2023-02-26 14.14.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/6d62ea00-88e7-f76c-36e4-8300961b8564.png)

### ④Fixtureの作成
Fixtureとは、Djangoに備わっている初期データやテスト用データを用意する機能です。
コマンド1つでデータを投入したり、データをテスト用データとして流用することができます。
```.tst:ターミナル
python3 manage.py migrate todo_app
```
次の様に表示されれば成功です。
![スクリーンショット 2023-02-26 14.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/ea6037b0-be8e-58ad-329f-fedf53204f22.png)

### ⑤DBの確認
todo_appフォルダ内にあるadmin.pyファイルを開き、以下の記述を行います。
```.tst:admin.py
from .models import Todo # Todoクラスのインポート

# Register your models here.
admin.site.register(Todo) # Todoモデルの追加
```
続いて管理者IDとパスワードの設定を行います。
```.tst:ターミナル
python3 manage.py migrate todo_app

ユーザー名 (leave blank to use '　　　　　　　　　　　　　　　　'): 
メールアドレス:
Password: 
Password (again): 
```
最後に「Superuser created successfully.」と表示されれば成功です。

では早速アプリを起動してみましょう。
```.tst:ターミナル
python3 manage.py runserver
```
を実行し、下図のように出てきたhtmｌにadminをつけてブラウザで開きます。
![スクリーンショット 2023-02-26 16.53.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/77cf4bf5-f3cf-50d8-311b-225f9a7eee9d.png)
```.tst:ブラウザ
http://127.0.0.1:8000/admin/
```
次の様な管理画面になりましたか？
![スクリーンショット 2023-02-26 16.55.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/3c9298ef-fab7-62c6-0e55-0a191f7e42a1.png)
ここで先ほど登録したユーザー名とパスワードでログインして、次の様な管理画面に遷移すれば成功です。
![スクリーンショット 2023-02-26 16.56.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/56da62d9-422d-5b51-cf24-b8b1ff99ffa6.png)
※ターミナルの方を見てみると色々とログが出ていると思いますが、ここでの説明は割愛します。
Ctrl + cでサーバの終了ができ、終了するとブラウザでアクセスできなくなります。

# Viewの作成
Viewではどのページを表示するかを決定する処理をしています。
まずはトップ画面を作成していきます。
todo_appフォルダ内にあるviews.pyファイルを開き、以下の記述を行います。
```.tst:views.py
from django.shortcuts import render, redirect  # レンダリング、リダイレクト機能のインポート
from django.views import View  # Viewクラスのインポート
from todo_app.models import Todo  # Todoクラスのインポート

# Create your views here.
# トップ画面
class IndexView(View):

    # Getリクエストの時の処理
    def get(self, request):
        # DBから更新日時降順でTODOを取得してテンプレートに返す
        todos = Todo.objects.all().order_by("-updated_at")
        # render(request, パス, 渡したいデータ（辞書形式))
        return render(request, "templates/todo/index.html", {"todos": todos})

    # Postリクエストの時の処理
    def post(self, request):
        # フォームに記載された内容をデータベースに記録する
        memo = request.POST["memo"]
        todo = Todo(memo=memo)
        todo.save()
        # リダイレクト(別のページに転送する)
        return redirect("/")
```

getとPostの違いは簡単に言うと
見るだけの時はget
変更するときはpost
のようなイメージです。

こちらのサイトでわかりやすく説明されています。
[「GETメソッド」と「POSTメソッド」の違い](https://wa3.i-3-i.info/diff7method.html#:~:text=Web%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%95%E3%82%93%E3%81%8B%E3%82%89Web%E3%82%B5%E3%83%BC%E3%83%90%E3%81%95%E3%82%93%E3%81%AB%E5%80%A4%E3%82%92,%E3%81%AE%E5%BE%8C%E3%82%8D%E3%81%AB%E3%81%8F%E3%81%A3%E3%81%A4%E3%81%91%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E5%BD%A2%E3%81%A7%E3%81%99,%E3%81%AA%E3%81%84%E3%81%A8%E3%81%93%E3%82%8D%E3%81%AB%E3%81%8F%E3%81%A3%E3%81%A4%E3%81%91%E3%81%BE%E3%81%99%E3%80%82)

**レンダリング**はある情報を形を変えて表現することです。
これをすることで、ただの文字の羅列ではなくて見やすいブラウザになります。

# HTMLのテンプレートの作成
まずはテンプレート格納用のフォルダをアプリフォルダ内に作成し、そこにindex.htmlを作成します。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/db3a9fad-0f3e-0643-f2fd-c42029f0b0f3.png)
```.tst:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <!-- Todoの新規登録用フォーム -->
    <div>
      <form action="/" method="post">
        {% csrf_token %}
        <input type="text" name="memo" />
        <input type="submit" value="送信" />
      </form>
    </div>
    <!-- 登録されたTodoを表示するリスト -->
    <ul>
      {% for todo in todos %}
      <li>
        <p>
          <span>{{ todo.memo}}</span>
          <span>{{ todo.updated.at }}</span>
        </p>
      </li>
      {% endfor %}
    </ul>
  </body>
</html>
```
# URLのルーティングを定義
ルーティングとは、URLなどにより処理を割り当てることです。
urls.pyを編集していきます。
```.tst:urls.py
from django.contrib import admin
from django.urls import path
from todo_app.views import IndexView  # IndexViewクラスのインポート

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", IndexView.as_view()),  # URLの最後が空白だったらIndexViewを返す
]
```
# テスト
ではここまで作成したものがどうなったのか、確認してみましょう。
```.tst:ターミナル
python3 manage.py runserver
```
```.tst:ブラウザ
http://127.0.0.1:8000
```
![スクリーンショット 2023-02-26 18.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/dfed6d87-cebd-9310-6373-cd23463a9900.png)
ここに文字を送信すると
![スクリーンショット 2023-02-26 18.28.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/19e6e5c5-0691-6374-0a1b-f5a0f1c48c6e.png)
リストに追加されているのが確認できました！！

管理者画面の方では編集や削除ができます。
![スクリーンショット 2023-02-26 18.29.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/ed9eab7b-419b-b6b4-7e47-22ba66f5e19a.png)