Djangoチュートリアル – その2

Django公式のチュートリアル「Writing your first Django app, part 2」を元に進んでいきます。

チュートリアル – その2では、以下の内容を学びます。

  • データベース
  • モデル
  • shell
  • 管理者用のadmin(アドミン)ページ
WARN
必ず「仮想環境(myenv)」が有効化されているか確認しましょう。ここからは先頭の(myenv)を省略して書いています。
app1 $ source myenv/bin/activate
(myenv) app1 $ cd mysite
(myenv) mysite $

データベースについて

データベースとは、色んな情報の集まりの事を言います。エクセルの様なものをイメージしてもらえば良いと思います。さらに、そのデータベースを管理するシステムがいくつかあります。

  • SQLite(エスキューライト)
  • MySQL(マイエスキューエル)
  • PostgreSQL(ポストグレスキューエル)
  • etc…

これらはDBMS(データベース管理システム)といい、単に「データベース」と言ったりもします。種類を覚える必要はないので安心してください。

Djangoには、元々pythonに組み込まれているSQLiteがデフォルトで設定されています。

作ったアプリを公開する場合は、何のデータベースを使うか予め設定する必要がありますが、これにはサーバーの知識が必要なので、今は気にせずデフォルトのSQLiteを使ってください。何の設定も必要ありません。


プロジェクトの基本設定

settings.pyの以下3つの設定は、プロジェクトを日本用にするものなので、プロジェクトを作成した時は必ず設定します。

  • IINSTALLED_APPS(インストールド・アップズ)
  • LANGUAGE_CODE(ランゲージ・コード)
  • TIME_ZONE(タイムゾーン)

mysiteディレクトリにあるsettings.pyで以下の内容を追加・修正し保存してください。

# 33行目くらい
INSTALLED_APPS = [
    'polls', # 作成したアプリを追加
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

# 106行目くらい
LANGUAGE_CODE = 'ja' # 日本語に変更

# 108行目くらい
TIME_ZONE = 'Asia/Tokyo' # アジア/東京に変更

データベースにテーブルを作る

テーブルは表という意味です。Djangoではターミナルでコマンドを実行するだけで、model(モデル)を元にデータベースにテーブルを作成してくれます。

pollsのmodels.pyに以下の内容を記入し保存します。

from django.db import models

# 質問のモデル
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

# 選択肢のモデル
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

モデルの説明

# モデルを定義する時はこの形で始まります。
class モデル名(models.Model):

# フィールドの定義は以下の形で定義します。(インデントを忘れないように)
    変数 = models.フィールドの種類(引数)

# 以下を日本語にすると
question_text = models.CharField(max_length=200)
名前は「question_text」とし、文字列を保存するための場所(CharField)とします。最大200文字とします。

変数

pythonで変数は代入を意味します。x = 1であれば、xに1を代入するという意味でxが1として扱われます。変数は必ず英語にしましょう。

ローマ字書きは基本NGです。例えば、名前のフィールドを作るのであれば、「namae」ではなく「name」にします。

フィールドの種類

何を保存する場所(フィールド)なのか設定します。

フィールドの種類は、日時を入力するフィールドや、数字を入力するフィールド、画像を保存するフィールド、他のテーブルと紐付けるフィールドなど沢山あります。

良く使うフィールドは大体決まっているので全てを覚える必要はありません。使ったことがあるフィールドを一つずつ覚えていきましょう。(フィールドの種類一覧(公式)

引数(ひきすう)

カッコの中身を引数と言います。オプション設定のようなものです。

上記では「max_length=200」が引数に指定されているので、最大文字数が200文字となります。

フィールドの種類によって、必須の項目があったり、設定できる内容が変わるという事だけ覚えておいて下さい。ちなみに、CharField(キャラ・フィールド)にはmax_lengthの引数が必須です。


modelに書いた内容を元に、下記のテーブルがデータベースに作成されることになります。

中身はまだ何も入っていないので????としています。

Questionモデル

idquestion_textpub_date
1????????

Choiceモデル

idquestionchoice_textvotes
1????????????

気づいた方もいるかもしれませんが、idのフィールドを設定していないのにidの列が作られていますね!

idは一意でなければならない(テーブルに一つしか存在してはいけない)ので、Djangoが自動で設定してくれます。

さっそくデータベースに反映させていきましょう!

INFO
仮想サーバーが起動している場合は、control + Cで停止します。

「python manage.py makemigrations アプリ名」で、データベースにmigrate(移行)するためのファイルを作成します。これをマイグレーションファイルと言います。

以下のコマンドでマイグレーションファイルを作成してください。

$ python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice

上記のような表示がでたら成功です!

エラーが出た場合は、内容をコピーして翻訳してみましょう。多分、models.pyかsettings.pyのコードに間違いや記入漏れがあります。

このコマンドはアプリ名を入れなくても実行できますが、その場合は全てのアプリのマイグレーションファイルが作られます。

WARN
マイグレーションファイルは、polls/migrationsディレクトリに入っています。ファイルの中身は変更しないようにしましょう。

次のコマンドを実行すると、マイグレーションファイルを元にデータベースにテーブルが作成されます。

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying polls.0001_initial... OK
  Applying sessions.0001_initial... OK

長いですが、OKがいっぱいでたと思います。

これで無事、データベースにテーブルが作成されました。


重要

モデルとマイグレーションファイルとデータベースの構造は、等しい必要があります。

マイグレーションファイルを変更したりすると、テーブルとの情報が一致しなくなるのでエラーが発生します。

モデルのフィールドを作成・追加・変更・削除した場合は、必ずmakemigrations → migrateの順で行って下さい。


テーブルにデータを入れてみる

今QuestionにもChoiceにも何もデータが入っていない状態ですが、中身を確認してみましょう。

以下のコマンドでshell(シェル)を起動させます。

shellは書いたコードの結果をリアルタイムで出力してくれます。

$ python manage.py shell

するとこんな表示になったと思います。

Python 3.9.1 (default, Aug 24 2022, 23:01:31) 
[Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 

shellを起動している時は、先頭に「>>>」が付きます。

下に記載した>>>の行のコードを、一行ずつコピペし実行してみてください。(>>>はコピーしない)

コード内に#で解説していますが、この部分はメモなので入力しなくてOKです。

# pollsモデルから、QuestionとChoiceを読み込みます。
>>> from polls.models import Question, Choice

# Questionのデータ(オブジェクト)を全て取得
>>> Question.objects.all()
<QuerySet []> # 何も入ってないので空のリストが返されます。

# timezoneを扱えるように読み込みます
>>> from django.utils import timezone

# Questionモデルの、question_textが「What's new?」で、pub_dateが「今の時間」のデータを、qとします。
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# qをQuestionのテーブルに保存します
>>> q.save()

# qのidを取得
>>> q.id
1

# qのquestion_textを取得
>>> q.question_text
"What's new?"

# qのpub_dateを取得
>>> q.pub_date
datetime.datetime(2022, 9, 4, 22, 31, 25, 364779, tzinfo=datetime.timezone.utc)

# qのquestion_textに「"What's up?"」を代入します。
>>> q.question_text = "What's up?"

# qをデータベースに保存します。
>>> q.save()

# qのquestion_textを取得
>>> q.question_text
"What's up?"

# Questionのデータ(オブジェクト)を全て取得
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

お疲れ様です。ちょっと面倒くさかったでしょう?

通常、こういったデータベースの操作はviews.pyに書いて処理します。

そしてもう一つ、最後の行は「Question object (1)」と書かれていて中身が分からないですね・・・

この問題はモデルの設定で解決できるので、models.pyで次の内容を追記し保存してください。

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self): # このブロックを追加
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self): # このブロックを追加
        return self.choice_text

モデルに「def __str __ (self):」を設定することで、出力の結果が「question_text」の内容になります。アンダーバーはstrの前後に2つずつです。

shellを再起動してもう一度試してみましょう。

control + D」でshellを終了し、「python manage.py shell」で起動。

# QuestionとChoiceをimportする
>>> from polls.models import Question, Choice

# Questionの全てのオブジェクトを取得
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

「What’s up?」と表示されたので、無事分かりやすい文字に変更できましたね!

モデルを作成する時は「def __str__(self):」を設定しておきましょう。

control + D」でシェルを終了します。

INFO
シェルはどんな結果が出力されるかすぐに知りたい時に使います。

管理者用のページを使う

shellで登録したり変更したりするのは面倒なので、管理者用のページを使いましょう!

管理ページはDjangoが用意してくれています!

まだ管理者が居ないので、以下のコマンドを使って管理者を作ります。(パスワード以外はコピペでOK)

$ python manage.py createsuperuser
# 名前は何でも良いのですが、ここでは「admin」を名前にします。
ユーザー名: admin 

# メアドをadmin@example.comにしておきます。
メールアドレス: admin@example.com

# 自由にパスワードを設定してください(忘れないでね)
# 入力した文字は表示されませんが、ちゃんと入力できています。
Password: ********
Password (again): ********
Superuser created successfully.

これで管理者を作成できたので、管理ページにログインできるようになりました。

ローカルサーバーを起動しましょう。

$ python manage.py runserver

「http://127.0.0.1:8000/admin/」にアクセスしてみて下さい。このadminは、前回やったのプロジェクトのurls.pyで設定されていたURLですね!

ログイン画面になるので、先程設定したユーザー名とパスワードを入力してログインしてください。

するとこんな画面が出てくると思います。

しかし、ここには先程作成したpollsモデルが表示されていません。

実は、管理ページにモデルの内容を表示させるには、admin.pyで設定する必要があります。

pollsのadmin.pyを開いて次の内容を追加し保存しましょう。

from django.contrib import admin
from .models import Question, Choice

# adminにQuestionモデルを登録
admin.site.register(Question)
admin.site.register(Choice)

これでQuestionモデルとChoiceモデルが管理ページで表示されるようになったので、http://127.0.0.1:8000/admin/のページを更新してみましょう。

POLLSのQuestionとChoiceが表示されました!

Qestionsをクリックすると、先程shellで作成した「What’s up!」が表示されているはずです。

Choiceにはまだ何も無いので、右上の「CHOICEを追加」ボタンから、「Not much」と「Good」を追加しておきましょう。


コマンドまとめ

# pollsのmodels.pyからマイグレーションファイルを作成
$ python manage.py makemigrations polls

# マイグレーションファイルを元にデータベースにマイグレート(移行)する
$ python manage.py migrate

# shellを起動
$ python manage.py shell
終了は「control + D」

# 管理者を作成する
$ python manage.py createsuperuser

まとめ

  • 色んな情報を保存するデータベースってのがある
  • プロジェクトを新しく作ったら日本用の設定に変える
  • 表のことをテーブルという
  • models.pyからマイグレーションファイルが作成される
  • マイグレーションファイルからテーブルが作成される
  • マイグレーションファイルの中身は変更しない
  • shellはコードの結果をリアルタイムで出力する
  • 管理ページの内容はadmin.pyで変更する

チュートリアル – その3