Djangoをちょっとだけ触ってみる(MTVの理解)

MTVとは

Model-Template-View(MTV)アーキテクチャの略。
Model・・・データの操作。データベースにアクセスしてデータ操作する。
Template・・・表示用の雛形。最終的な出力結果(HTML, JSONなど)をレスポンスする。
View・・・出力のためのデータ準備。リクエストデータを受け取り、Modelを呼び出し、Templateに処理結果を引き渡す。

リクエスト

View ⇄ Model

Template

レスポンス

Model-View-Controller(MVC)と混同しやすいので整理しておく。

役割MTVMVC
データの操作ModelModel
表示用の雛形TemplateView
データの準備ViewController

MTVはプロジェクト内の各アプリごとに作成する。
以降の説明でパスを示す時は、プロジェクトルートから記載する。
今回のプロジェクトルートはquick_djangoとする。

この記事で追加修正するファイルの在り処

 1quick_django
 2├── main
 3│   ├── models.py
 4│   ├── templates
 5│   │   └── main
 6│   │       ├── list.html
 7│   │       └── temp.html
 8│   ├── urls.py
 9│   ├── views.py
10├── quick_django
11│   ├── urls.py

ルーティング情報の設定

ルーティング情報設定ファイルは、プロジェクトとアプリのそれぞれにある。

  1. quick_django/quick_django/urls.py
  2. quick_django/main/urls.py

[ quick_django/quick_django/urls.py ]
1.のurlpatternsにpath('main/', include('main.urls'))を追加する。
2.のファイルをincludeしている。

1urlpatterns = [
2    path('main/', include('main.urls')),
3    path('admin/', admin.site.urls),
4]

なお、3行目は管理サイトの表示で使われるが、この記事では説明省略する。

[ quick_django/main/urls.py ]
2.のurlpatternsを以下のように設定してみる。

1urlpatterns = [
2    path ('', views.index, name='index'),
3    path ('temp', views.temp, name='temp'),
4    path ('list', views.list, name='list'),
5]

これにより、http://localhost:8080/mainでアクセスするとmainアプリのViewで定義されているindex関数が動き、同様にhttp://localhost:8080/main/tempでアクセスするとmainアプリのViewで定義されているtemp関数が動く。listも同様。

[ pathの構文 ]
path(route, include(path))
  route : URLパターン
  path : includeするモジュール

path(route, view[, path])
  route : URLパターン
  view : View関数
  name : ルート情報の名前

Viewの基本

quick_django/main/views.pyがViewの実態。
これを開いて次のようにコーディングしてみる。

[ quick_django/main/views.py ]

 1from django.shortcuts import render
 2from django.http import HttpResponse
 3from .models import Book
 4
 5# Create your views here.
 6def index(request):
 7    return HttpResponse('こんにちは、世界!')
 8
 9def temp(request):
10    context = {
11        'msg':'こんにちは、世界!'
12    }
13    return render(request, 'main/temp.html', context)
14
15def list(request):
16    books = Book.objects.all()
17    return render(request, 'main/list.html', {'books':books})

各関数は引数としてHttpRequestオブジェクトを受け取り、HttpResponseオブジェクトを返す。

[ renderの構文 ]
render(request, template[, context])
  request : HttpRequestオブジェクト
  template : Templateへのパス(アプリルートのtemplatesディレクトリを基点とする)
  context : View変数(辞書)
  戻り値 : contexttemplate をレンダリングして、その結果をHttpResponseオブジェクトとして返す

Templateの基本

上記のView関数temp, listのrenderにおいてパラメータにTemplateパスを指定したので、そのファイルを以下のように作成してみる。

アプリ作成時にViewとModelの実態であるviews.pyとmodels.pyは雛形として自動作成されるが、Templateについては実態となるファイルは用意されないので、新規作成する。
まず quick_django/main/templates ディレクトリを作成する。
さらにその下にアプリのディレクトリを作成するのが一般的らしい。
さらにその下にTemplateの実態となるファイルを作成する。

[ quick_django/main/templates/main/temp.html ]

 1<!DOCTYPE html>
 2<html lang="ja">
 3<head>
 4<meta charset="UTF-8" />
 5<title>速修Django</title>
 6</head>
 7<body>
 8<p>{{ msg }}</p>
 9</body>
10</html>

8行目の{{ msg }}について。View関数のrenderで渡された context のmsgがここにレンダリングされる。 ブラウザよりhttp://localhost:8080/main/tempでリクエストすると、こんにちは、世界!が表示される。

[quick_django/main/templates/main/list.html]

 1<!DOCTYPE html>
 2<html lang="ja">
 3<head>
 4<meta charset="UTF-8" />
 5<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
 6<title>速習Python</title>
 7</head>
 8<body>
 9<table class="table">
10<thead>
11<tr>
12<th>ISBNコード</th><th>書名</th><th>価格</th><th>出版社</th><th>刊行日</th>
13</tr>
14</thead>
15<tbody>
16{% for b in books %}
17<tr>
18<td>{{ b.isbn }}</td>
19<td>{{ b.title }} </td>
20<td>{{ b.price }} </td>
21<td>{{ b.publisher }} </td>
22<td>{{ b.published|date:'DATE_FORMAT' }} </td>
23</tr>
24{% endfor %}
25</tbody>
26</table>
27</body>
28</html>

16行目では、View関数のrenderで渡されたbooksがここに入ってきて、1件ずつ取り出されて繰り返し処理している。
18〜22行目では、この後で示すModelクラス変数が入ってくる。

この後で示すModelクラス作成後にDB設定&管理画面よりデータ投入し、http://localhost:8080/main/listでリクエストすると下図のような結果が得られる。

Modelの基本

ここではDB設定などの準備はすでに実施済みであることを前提とする。

quick_django/main/models.pyがModelの実態。
これを開いて次のようにModelクラス(ここではBookクラス)を作成してみる。
Modelクラスはテーブル定義を表す。
またModelクラス変数はTempleteで参照される。

[ quick_django/main/models.py ]

 1from django.db import models
 2
 3# Create your models here.
 4class Book(models.Model):
 5    isbn = models.CharField(
 6        verbose_name = 'ISBNコード"',
 7        max_length = 20
 8    )
 9    title = models.CharField(
10        verbose_name = '書名',
11        max_length = 100
12    )
13    price = models.IntegerField(
14        verbose_name = '価格',
15        default = 0
16    )
17    publisher = models.CharField(
18        verbose_name = '出版社',
19        max_length = 50,
20        choices = [
21            ('翔泳社', '翔泳社'),
22            ('技術評論社','技術評論社'),
23            ('秀和システム','秀和システム'),
24            ('SBクリエイティブ','SBクリエイティブ'),
25            ('日経BP','日経BP'),
26        ],
27    )
28
29    published = models.DateField(
30        verbose_name = '刊行日'
31    )
32
33    def __str__(self):
34        return f'{self.title}({self.publisher}/{self.price}円)'

一番下の__str__メソッドは必須ではないが、Modelの識別情報として定義しておく。
Modelクラス変数の構文については、特に示さなくても上記を見れば感覚的にわかるので、説明省略する。

関連ページ