簡易書籍一覧表示アプリケーションの説明
6.3 簡易書籍一覧表示アプリケーションの説明
作成したアプリケーションをもとに、データベースアクセス処理が実際どのような流れで動作しているのかを説明していきます。
6.3.1 Modelクラス(Bookクラス)
まず初めに、今回新たに登場したModelクラスのサブクラスであるBookクラスについて解説します。
■ソースコード
【ファイル名:models.py】
from django.db import models
class Book(models.Model):
#isbn
isbn = models.CharField(max_length=128,primary_key=True)
#タイトル
title = models.CharField(max_length=128)
#価格
price = models.IntegerField()
Modelは、該当のプロジェクトのディレクトリ(bmsdjango)直下にある「models.py」内に定義します。
Modelとして3~12行目でBookクラスを定義しており、Modelは「django.db.models.Model」のサブクラスであるため、3行目で「class Book(models.Model)」と記載されています。
class Book(models.Model):
また先ほど説明した通り、Modelはデータベースと紐づけられ、Model名つまりはModelのサブクラス(Book)をテーブル名に対応し、また6~12行目で宣言されている各変数は、列名に該当します。
#isbn
isbn = models.CharField(max_length=128,primary_key=True)
#タイトル
title = models.CharField(max_length=128)
#価格
price = models.IntegerField()
これらの変数は、列名だけでなく属性や文字数など、どのような列(カラム)にするのかを決定するためのものです。
具体的には、isbnやtitleのように文字列を格納する場合には、models.CharFielsメソッドの戻り値を変数に代入します。
引数max_lengthには文字数、引数primary_keyにはprimary_key列であればtrueを代入します。
またpriceのような整数値を格納する場合には、models.IntegerFieldメソッドの戻り値を変数に代入します。
以上、Modelの基本形について以下でまとめました。
■Model(modelのサブクラス)の基本形
from django.db import models
class テーブル名(models.Model):
#文字列型のprimary_key列
列名 = models.CharField(max_length=文字数,primary_key=True)
#文字列型の列
列名 = models.CharField(max_length=文字数)
#整数型の列
列名 = models.IntegerField()
6.3.2 Model(Bookクラス)のマイグレーション
Modelは、クラス名(Book)がテーブル名、クラス内で宣言されている各変数が列名(isbn、title、price)に該当しますが、Modelを作成しただけではデータベース上にテーブルは作成されません。
上記のModelに対応するテーブルとしてデータベースに反映させるために、マイグレーションという処理を実行します。
マイグレーションとはデータの移行や更新を意味します。
先ほど「①マイグレーションファイルの作成」、「②マイグレーションの実行」というコマンドをターミナルで実行しましたが、こられの一連の操作がデータベースに反映させるためのマイグレーションに該当します。
マイグレーションファイルとはデータベースに反映させる内容について書かれたファイルです。
Modelの定義後にマイグレーションファイルを作成すると、ファイル内にはModelの内容を元に必要なテーブルの情報(テーブル名や各列の情報)がデータベースに反映させる情報として記載されます。
作成したマイグレーションを実行することで、マイグレーションファイルに書かれた内容がデータベースに反映されるため、結果的にModelの内容に対応したテーブルが作成されます。
図 6.3.1:マイグレーションの流れ
6.3.3 urls.py
続いてurls.pyを確認しましょう。
■ソースコード
【ファイル名:django_basic/urls.py】
前章でも説明した内容から、9行目から「path(‘loginform/’, include(‘bmsdjango.urls’))」は、「http://localhost:8000/bmsdjango/●●●」にアクセスした場合、「bmsdjango」ディレクトリ直下の「urls.py」が読み込まれることがわかります。
「bmsdjango」ディレクトリ下の「urls.py」を確認すると、「http://localhost:8000/bmsdjango/list」にアクセスすると「list」に該当する要素として、「listView関数」が実行されることがわかります。
【ファイル名:bmsdjango /urls.py】
from django.urls import path
from . import views
urlpatterns = [
path('list', views.listView, name='list'),
]
6.3.4 View(view.py)
「http://localhost:8000/bmsdjango/list」にアクセスすると、「listView関数」が実行されることがわかりました。
続いてViewに該当する、listView関数の処理を確認していきましょう。
■ソースコード
【ファイル名:bmsdjango/views.py】
from django.shortcuts import render
from .models import Book
def listView(request):
#Bookオブジェクトのリストを取得する
bookList = Book.objects.all()
#エラーの有無でフォワード先を呼び分ける
params ={
'bookList':bookList,
}
return render(request, 'list.html',params)
7行目ではModelであるBookクラスを介して「objects.all()」メソッドを呼び出しています。
「objects.all()」メソッドは、Bookクラスの継承元である「django.db.models.Model」で定義されているメソッドです。
#Bookオブジェクトのリストを取得する
bookList = Book.objects.all()
bookListには、「objects.all()」メソッドの戻り値として、Bookテーブルの全行のレコードが取得できます。
具体的には、リストのような配列(QuerySet型)が戻り値として返り、各要素にはBookテーブルの対応する行の各列の値がまとめられた「Book object()」が格納されます。
図 6.3.2:objects.allメソッドの流れ
6.3.5 list.html(テンプレートファイル)
最後に、画面にデータを表示するテンプレートを見ていきましょう。
■ソースコード
【ファイル名:list.html】
<!DOCTYPE html>
{%load static%}
<html>
<head>
<title>書籍一覧</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}"/>
</head>
<body>
<!-- ブラウザ全体 -->
<div id="wrap">
<!--ヘッダー部分 -->
<header>
<div class="container">
<h1>書籍管理システムWeb版 Ver.1.0</h1>
</div>
</header>
<!-- メニュー部分 -->
<div id="menu">
<div class="container">
<!-- ナビゲーション -->
<div id="nav">
<ul>
<li><a href="./">[メニュー]</a></li>
<li><a href="./insert">[書籍登録]</a></li>
<li><a href="{% url 'list' %}”>[書籍一覧]</a></li>
</ul>
</div>
<!-- ページタイトル -->
<div id="page_title">
<h2>書籍一覧</h2>
</div>
</div>
</div>
<!-- 書籍一覧のコンテンツ部分 -->
<div id="main" class="container">
<!-- 検索フォーム -->
<form class="inline-block" action="/search" >
ISBN <input type="text" name="isbn">
TITLE <input type="text" name="title">
価格 <input type="text" name="price">
<input type="submit" value="検索">
</form>
<form class="inline-block" action="{% url 'list' %}" >
<input type="submit" value="全件表示">
</form>
<table class="list-table">
<thead>
<tr>
<th>ISBN</th>
<th>TITLE</th>
<th>価格</th>
<th>変更 / 削除</th>
</tr>
</thead>
<tbody>
{% for book in bookList %}
<tr>
<td><a href="#">{{book.isbn}}</a></td>
<td>{{book.title}}</td>
<td>{{book.price}}</td>
<td>
<a href="#">変更</a>
<a href="#">削除</a>
</td>
<tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- フッター部分 -->
<footer>
<div class="container">
<h4>Copyright© 2016 All Right Reserved.</h4>
</div>
</footer>
</div>
</body>
</html>
2行目の「load static」により、「static ファイル名」と記載することで「static」ディレクトリ内の該当のファイルを指定することができます。
そのため6行目では、「bmsdjango/static/」内の「css/style.css」が読み込まれるので、該当のCSSが適用されます。
<html>
<head>
<title>書籍一覧</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}"/>
</head>
58~68行目では繰り返し処理が行われています。Viewから引き継がれた「bookList」の各要素を取り出すための繰り返し処理です。
{% for book in bookList %}
<tr>
<td><a href="#">{{book.isbn}}</a></td>
<td>{{book.title}}</td>
<td>{{book.price}}</td>
<td>
<a href="#">変更</a>
<a href="#">削除</a>
</td>
<tr>
{% endfor %}
各要素はカウンタ変数「book」に格納されます。変数bookには、Bookテーブルの対応する行(レコード)の各列の情報が格納され、「変数名.列名」で該当する列のデータを取得できます。
そのため「book.isbn」ではisbn列のデータ、「book.title」ではtitle列のデータ、「book.price」ではprice列のデータを取得します。
図 6.3.3:objects.allメソッドの流れ