前回は、電子書籍「速習Django3」に沿いつつ、しかし別の方法(Anacondaによりパッケージ管理)で、環境作成(Python動作環境、必要なライブラリのインストール)、仮想環境作成、新規プロジェクト作成、初期規定のアプリ表示、機能追加したアプリをviews.pyから直接出力表示するところまで実施し、それに対しての、ふりかえり(反省)を行ってみました。
(仮想環境名は「Python_Django_sokusyu3_01」、新規プロジェクト名は「Python_Django_sokusyu3_01_PJ」、新規アプリケーション名は「main」でした)
今回は、Django標準管理画面から、SQLiteデータベースを操作してみました。
以下は、その作業記録(備忘録)です。
1.管理用ユーザー登録
(1)管理用ユーザー作成コマンド実行
python manage.py createsuperuser

(2)ユーザー名、メールアドレス、パスワード指定

(3)動作確認
ブラウザ起動後、管理画面(http://localhost:8000/admin)を表示し、
上記のユーザー名、パスワードを入力して、ログインします。

この時点では、なにもテーブルが表示されていません。
(※書籍では先に以下の登録をしてから、管理画面を表示していました)
以下の手順で、テーブル(モデル)を登録しておきます。
2.テーブル登録 / admin.py
mainアプリケーションフォルダ配下の、admin.pyに、以下の様に、テーブル(ここでは、Booksテーブル)を登録しておきます。
# main / admin.py への登録内容
from .models import Book
admin.site.register(Book)

3.データ登録 / models.py
mainアプリケーションフォルダ配下の、models.pyに、以下の様に、データを登録しておきます。
このmodels.py
ファイルは、Djangoのモデル定義を含んでいます。モデルは、データベース内のテーブルとして表されるオブジェクトです。以下でコードを解説します。
(1)モジュールのインポート
from django.db import models
from django.urls import reverse
from django.core.validators import RegexValidator, MinValueValidator

(2)モデルクラスの定義
以下では、各モデルクラス(Book、Review、Author、User)のフィールドとメソッドを定義します。
各フィールドには、データベースのカラムとしての属性やバリデーションが指定されています。
__str__
メソッドは、オブジェクトの文字列表現を返します。
get_absolute_url
メソッドは、オブジェクトの絶対URLを返します。
このmodels.py
ファイルは、Djangoのモデルを定義するためのものであり、データベースのテーブルとして使用されます。
(2-1)1つめのモデルクラス(テーブル)定義 / Book
①テーブル
class Book(models.Model):

②フィールド
#ISBNコード
isbn = models.CharField(
verbose_name=’ISBNコード’,
max_length=20,
validators=[ #←validators
を使用して正規表現のバリデーションを指定しています。
RegexValidator(
r’^978-4-[0-9]{4}-[0-9]{4}-[0-9X]{1}$’,
message=’ISBNコードは正しい形式で指定してください。’)
]
)

#署名
title = models.CharField(
verbose_name=’書名’,
max_length=100
)

#価格
price = models.IntegerField(
verbose_name=’価格’,
default = 0,
validators=[ #←validators
を使用して最小値のバリデーションを指定しています。
MinValueValidator(
17,
message=’価格は正の整数で指定してください。’
)
]
)

#出版社
publisher = models.CharField(
verbose_name=’出版社’,
max_length=50,
choices = [ #←choices
を使用して、選択肢を指定しています。
(‘翔泳社’, ‘翔泳社’),
(‘技術評論社’, ‘技術評論社’),
(‘秀和システム’, ‘秀和システム’),
(‘SBクリエイティブ’, ‘SBクリエイティブ’),
(‘日経BP’, ‘日経BP’),
],
)

#刊行日
published = models.DateField(
verbose_name=’刊行日’
)

③メソッド
(ⅰ)オブジェクト文字列表現メソッド定義
def __str__(self):
return f'{self.title}({self.publisher}/{self.price}円)’
※__str__
メソッドは、オブジェクトを文字列として表現するためのメソッドです。ここでは、title
、publisher
、price
を組み合わせて表現しています。

(ⅱ)オブジェクトの絶対URLを返すためのメソッド定義
# class Meta:
# ordering = (‘published’,)
def get_absolute_url(self):
return f’details/{self.id}’
※get_absolute_url
メソッドは、オブジェクトの絶対URLを返すためのメソッドです。
ここでは、オブジェクトのIDを使用してURLを作成しています。
(2-2)2つめのモデルクラス(テーブル)定義 / Review
ここで定義するReview
モデルはBook
モデルとの関連を持ち、名前と本文を表すフィールドを持っています。また、__str__
メソッドをオーバーライドして、オブジェクトを文字列として表現する方法を指定しています。
class Review(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE) #←ForeignKey
として定義
Book
モデルとの関連を表す
name = models.CharField(
verbose_name=’名前’,
max_length=20
)
※book
フィールドは、ForeignKey
として定義されています。
これは、Book
モデルとの関連を表すフィールドです。on_delete=models.CASCADE
は、関連するBook
オブジェクトが削除された場合に、このReview
オブジェクトも同時に削除する設定です。
body = models.TextField(
verbose_name=’本文’,
max_length=255
)
※body
フィールドはTextField
で、本文を表します。max_length
を指定していますが、TextField
は任意の長さのテキストを格納するため、指定した長さよりも長いテキストも保存できます。
def __str__(self):
return f'{self.name}: {self.body[:10]}’
※__str__
メソッドは、オブジェクトを文字列として表現するためのメソッドです。
ここでは、name
とbody
の一部(最大10文字)を組み合わせて表現しています。
このメソッドが定義されることで、Review
オブジェクトが文字列として表示される際に、指定した形式で表示されます。
(2-3)3つめのモデルクラス(テーブル)定義 / Author
ここで定義するAuthor
モデルは複数のBook
モデルとの多対多の関連を持ち、名前と住所を表すフィールドを持っています。__str__
メソッドによって、オブジェクトが文字列として表示される際に名前が使用されます。
class Author(models.Model):
books = models.ManyToManyField(Book)
#↑ books
フィールドは、ManyToManyField
として定義されています。
これは、Book
モデルとの多対多の関連を表すフィールドです。
つまり、1つのAuthor
オブジェクトは複数のBook
オブジェクトと関連付けることができます。
name = models.CharField(
verbose_name=’名前’,
max_length=20
)
address = models.CharField(
verbose_name=’住所’,
max_length=100
)
def __str__(self):
return self.name
#↑ __str__
メソッドは、オブジェクトを文字列として表現するためのメソッドです。
ここでは、単純にname
フィールドの値を返しています。
(2-4)4つめのモデルクラス(テーブル)定義 / User
ここで定義するUser
モデルはAuthor
モデルとの一対一の関連を持ち、ユーザー名とメールアドレスを表すフィールドを持っています。__str__
メソッドによって、オブジェクトが文字列として表示される際にユーザー名が使用されます。
class User(models.Model):
author = models.OneToOneField(Author, on_delete=models.CASCADE)
#↑ author
フィールドは、OneToOneField
として定義されています。
これは、Author
モデルとの一対一の関連を表すフィールドです。
つまり、1つのUser
オブジェクトは1つのAuthor
オブジェクトと関連付けられます。
handle = models.CharField(
verbose_name=’ユーザー名’,
max_length=20
)
email = models.CharField(
verbose_name=’メールアドレス’,
max_length=100
)
def __str__(self):
return self.handle
(3)動作確認(表示)
①ブラウザーの表示を更新します。

すると、MAINアプリケーション配下に、Booksテーブルが、登録されているのが分かります。
③レコードを登録します。
※以下の様に、もう予め、書籍登録に必要なデータ項目が設定されていました。
※なるほど、(この書籍を読み進めて気づいたのですが)ある程度のテンプレートが、Django自体に登録されているわけですね…。
※MS-Access等のテンプレートDBみたいなものらしいです…。
以下の様に、準備されている項目に、データを登録してきます。(参照書籍の内容ですね^^ )
最後に保存ボタンを押します。

④エラーが表示されました!
書籍の通りに、作業を進めたつもりなのですが… 以下のエラー画面が表示されました。

…あれ、おかしいなぁー…と、電子書籍「速習Django3速習シリーズ」の2.3章を読み返しながら、コマンドを打ったりしていたら、以下の様に、きちんとデータが反映された画面が表示されました。
※すいません、さっき(上記まで)と、何が違うのか(何を間違っていたのか)記録してなくて、忘れました(別途で記載したいと思います(;^ω^))

⑤データ追加
上記と同様に、複数の書籍を(サンプルとして)登録しました。

ここまでで、なんとか、電子書籍「速習Django3速習シリーズ」のサンプルデータを登録しました。
4.ビュー関数の登録
上記で登録した情報を、表示するためのビュー関数を登録しました。
(1)テンプレート追加 / list.html
(テンプレートmainアプリケーション配下に)list.htmlを新規作成し、以下の通りに編集します。

(2)ルート情報追加 / urls.py
上記フォルダのurls.py にルート定義を追加します。

(3)動作確認
ブラウザーで「http://localhost:8000/main/list」と指定して、listビューを表示する。
…すると、あれ、また、以下のエラーが表示されました…。(なんでだろう…)

…なんでだろう…なんでだろう…と、再度、上記電子書籍を読み返し…原因が分かりました。
上記①の、list.html の編集中、
17行目 : % for b in books %
これが間違っていました。
正しくは、
17行目 : { % for b in books % }
でした(;^ω^)…

ここを修正したら、以下の通り、登録した情報が正しく表示されました。

ここまでで、なんとか、電子書籍「速習Django3速習シリーズ」のPart2まで完了しました。^^