このタイミングでモデルとマイグレーションファイル,フォームの要素についてそれらの関連を確認しておこう.Django は,記述したモデルからマイグレーションファイルやフォームを自動的に作成できることが特長である.まず,すでに記述したモデルの内容を確認する.
comments/models.py (抜粋)
class Comment(models.Model):
title = models.CharField(max_length=200)
body = models.CharField(max_length=1000)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
ここで実行したマイグレーションのコマンドによって生成されたマイグレーションファイルには 0001 から順に番号が振られる.その内容を確認すると,モデルに記述したフィールドが設定されていることがわかる.
comments/migrations/0001_initial.py
# Generated by Django 3.1.1 on 2020-09-06 16:44
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('body', models.CharField(max_length=1000)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
),
]
sqlite3 でテーブルのスキーマを確認すると,全てのカラムに NOT NULL 属性が設定されていることがわかる.
(base) C:\Users\lecture\Documents\django\django_comment>sqlite3 db.sqlite3 ⏎ SQLite version 3.31.1 2020-01-27 19:55:54 Enter ".help" for usage hints. sqlite> .tables ⏎ auth_group comments_comment auth_group_permissions django_admin_log auth_permission django_content_type auth_user django_migrations auth_user_groups django_session auth_user_user_permissions sqlite> .schema comments_comment ⏎ CREATE TABLE IF NOT EXISTS "comments_comment" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(200) NOT NULL, "body" varchar(1000) NOT NULL, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL ); sqlite> .exit ⏎ (base) C:\Users\lecture\Documents\django\django_comment>
また,投稿フォームや更新フォームでは title と body だけが表示されるようにした.
comments/forms.py (抜粋)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('title', 'body')
widgets = {
'title': forms.TextInput(attrs={
'class': 'form-control'
}),
'body': forms.TextInput(attrs={
'class': 'form-control'
}),
}
labels = {
'title': 'タイトル',
'body': '本文',
}
Web ブラウザで新規投稿フォームを表示して,そのソースコードを確認する(Google Chrome では「表示」→「開発 / 管理」→「ソースを表示」メニューを,Firefox では「ツール」→「ウェブ開発」→「ページのソース」メニューをクリックする).
生成された新規投稿フォームの HTML ソース
<div class="container">
<h1 class="my-5">コメントの投稿</h1>
<form method="POST">
<input type="hidden" name="csrfmiddlewaretoken" value="K8udatbth8GlhLZmCmPQfiXoZKnOmkHq2yhCV7J2S4dleowCpQ58oicrKPOae2KW">
<p><label for="id_title">タイトル:</label> <input type="text" name="title" class="form-control" maxlength="200" required id="id_title"></p>
<p><label for="id_body">本文:</label> <input type="text" name="body" class="form-control" maxlength="1000" required id="id_body"></p>
<button type="submit" class="btn btn-primary">コメントを投稿する</button>
</form>
</div>
上のソースを見ると,title と body のテキストボックスには required 属性が設定されている.これは,データベースのカラムに NOT NULL 属性が設定されているからである.よって,新規投稿フォームや更新フォームで title や body を空のままにして投稿しようとしても,Web ブラウザがその検証を行ってくれる.
Can I Use (https://caniuse.com/) で確認すると,required 属性はほとんどの Web ブラウザでサポートされているが,HTML の全ての機能が全ての Web ブラウザでサポートされているとは限らない.また,半角スペースだけが入力されたときには Web ブラウザを通過して,Django 側でエラーになるという問題点がある.更に,空の投稿は検証できるが,title や body にそれぞれの上限文字数である 200 文字や 1000 文字以上が投稿されたときにのエラー表示なども Web ブラウザだけに任せるのではなく,Django 側でも検証しておいたほうが安全である.次に,入力内容の検証を行ってみよう.