DjangoにおけるMVCモデルについて図解した

# はじめに
Djangoの処理の流れが、イマイチ理解できなかったのと、Djangoを触ったことない人向けに簡単に説明したいなと思いまとめました。


# MVCモデルとは

MVCモデルは、Model（モデル）、View（ビュー）、Controller（コントローラ）の3つの要素で構成され

| 要素 | 役割 |
| --- | --- |
| Model | データベースやファイルなどのデータを管理する役割を持ちます。データの取得や更新、保存などの処理を行います。 |
| View | ユーザーが見ることができる画面を表示する役割を持ちます。HTML、CSS、JavaScriptなどを使って画面を構成します。 |
| Controller | ユーザーからの入力を処理し、ModelとViewを制御する役割を持ちます。Viewからの入力を受け取り、Modelにデータを要求したり、Viewを更新したりします。 |

このように、MVCモデルはアプリケーションを3つの部分に分割し、それぞれが特定の役割を担当しています。この分割により、アプリケーションの保守性や拡張性が向上し、開発効率が高まることが期待されています。

```mermaid
graph LR
A[User] --> B[View]
B --> C[Controller]
C --> D[Model]
D --> B
B --> A
```

## DjangoアプリケーションにおけるMVCモデルについて

```mermaid
graph LR
 H["templates"]
subgraph ユーザー側
    A[ユーザー]--> |URLにアクセス GET|C["urls.py"]

    subgraph Controller
        C -->D["views.py"]
    end
   D-->|Htmlに情報渡す|View

    subgraph Models
    D --> E["Model.py"]
 
   	end

    subgraph View
        H
    end
    H --> |ページ表示|A
end

subgraph サーバ

        E --> I["データベースとやりとり(CRUD)"]
end
  I-->E

```

スクリプト名を含めた表は以下の通りです。

| 要素 | スクリプト名 | 役割 |
| --- | --- | --- |
| Model | models.py | アプリケーション内のデータを管理する役割を持ちます。Djangoでは、models.pyに定義されたモデルが、データベースのテーブルとして生成されます。データの取得や更新、保存などの処理を行います。Djangoのモデルは、オブジェクト関係マッピング（ORM）を利用して、データベースとのやりとりを行います。 |
| View | templates 
views.py | ユーザーが見ることができる画面を表示する役割を持ちます。Djangoでは、views.pyに定義された関数が、URLパターンに応じたビューとして呼び出されます。ビューは、テンプレートエンジンを使って、HTMLなどのファイルをレンダリングし、ユーザーに表示します。 |
| Controller | urls.py, views.py | ユーザーからの入力を処理し、ModelとViewを制御する役割を持ちます。Djangoでは、urls.pyに定義されたURLパターンが、views.pyの関数を呼び出す役割を担います。URLパターンに応じたビューを呼び出し、ビューからの入力を受け取り、Modelにデータを要求したり、Viewを更新したりします。 |

Controllerはurls.pyとviews.pyの両方で定義されていることに注意してください。urls.pyは、URLパターンとビューの関連付けを行います。views.pyは、ビューの実装を行います。これにより、コントローラの役割が分離され、コードの再利用性が高まります。

```html
my_project/
├── my_app/         # アプリケーションのルートディレクトリ
│   ├── __init__.py # Pythonのパッケージとして認識するための空のファイル
│   ├── admin.py    # Djangoの管理画面で表示するモデルの登録や設定を行うファイル
│   ├── apps.py     # アプリケーションの設定を記述するファイル
│   ├── forms.py    # フォームの定義を行うファイル
│   ├── models.py   # アプリケーション内のデータモデルを定義するファイル
│   ├── tests.py    # アプリケーションのテストを定義するファイル
│   ├── urls.py     # アプリケーション内のURLパターンとビューの関連付けを定義するファイル
│   ├── views.py    # ビューの定義を行うファイル
│   └── templates/  # テンプレートファイルを格納するディレクトリ
│       └── my_app/ # アプリケーション別のテンプレートを格納するディレクトリ
│           ├── base.html     # ページの共通部分を定義するためのテンプレートファイル
│           ├── todo_list.html# ToDoリストの一覧表示を行うためのテンプレートファイル
│           └── todo_add.html # ToDoリストの追加を行うためのテンプレートファイル
└── my_project/     # プロジェクトのルートディレクトリ
    ├── __init__.py # Pythonのパッケージとして認識するための空のファイル
    ├── settings.py # プロジェクトの設定を記述するファイル
    ├── urls.py     # プロジェクト全体のURLパターンとアプリケーションのURLパターンを関連付けるファイル
    └── wsgi.py     # プロジェクトをウェブサーバーに接続するためのファイル
```

## 実装例

具体的な例を示しながら、Model, View, Controllerの役割について説明します。

まず、Djangoアプリケーションの場合を見てみましょう。以下は、ToDoリストを管理するアプリケーションの場合のModel, View, Controllerの概念図です。

- Model: ToDoリストのデータを管理するためのModelを定義します。以下は、ToDoリストのモデルの例です。

```python
from django.db import models

class TodoItem(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    is_completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

```

このモデルは、ToDoリストのタイトル、説明、完了フラグ、作成日時、更新日時を管理します。

### View

ToDoリストを表示するためのViewを定義します。以下は、ToDoリストを表示するためのビューの例です。

```python
from django.shortcuts import render
from .models import TodoItem

def todo_list(request):
    todo_items = TodoItem.objects.all()
    context = {'todo_items': todo_items}
    return render(request, 'todo_list.html', context)

```

このビューは、ToDoリストのモデルからデータを取得し、テンプレートに渡すコンテキストを作成して、HTMLファイルをレンダリングします。

### Controller

ToDoリストを制御するためのControllerを定義します。以下は、ToDoリストを追加するためのControllerの例です。

```python
from django.shortcuts import render, redirect
from .forms import TodoItemForm

def todo_add(request):
    if request.method == 'POST':
        form = TodoItemForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('todo_list')
    else:
        form = TodoItemForm()
    context = {'form': form}
    return render(request, 'todo_add.html', context)

```

このコントローラは、ToDoリストのフォームからデータを取得し、モデルに保存します。保存が成功した場合は、ToDoリストの一覧ページにリダイレクトします。保存が失敗した場合は、フォームを再表示します。