はじめに
前回は、ListViewとDetailViewを用いて登録したTodoの一覧表示と詳細を表示しました。
今回は、CreateView(登録)とUpdateView(更新)とDeleteView(削除)を用いて、Todoアプリに必要のTodoの登録、更新、削除の機能を実装します。
今回でdjangoで作るTodoアプリは完成します。
Todo管理のWebアプリの動作イメージは下記となります。
参考にした書籍
ポチップ
ポチップ
ポチップ
Todoを登録する際の動作フロー
Todoを登録するときの動作フローは下記となります。Todoを更新する際も同様の動作になります。
テンプレートシステムを用いることで、各ページで共通して使用しているヘッダーやボタンの記述をbase.html、_form.htmlにまとめています。
- ユーザーがブラウザを通じて特定のURLにアクセスします。
- Webサーバーが受け取ったHTTPリクエストをdjangoのルーティングシステム(urls.py)に渡します。
- プロジェクトのurls.pyがリクエストを適切なアプリケーション(この場合はtodocreate)のurls.pyにルーティングします。
- アプリ(この場合はtodocreate)のurls.pyはリクエストを関連するビュー(views.py)に渡します。
- ビューは、必要に応じてデータベースからデータを取得するためのクエリをデータベースに送信し、情報を取得します。
- データベースから取得した情報、commonのforms.py、base.html、create.html、_form.htmlをビュー(views.py)によって組み合わせられます。
- ビュー(views.py)は最終的なHTTPレスポンスを生成し、Webサーバーに返します。
- WebサーバーはこのHTTPレスポンスをユーザーのブラウザに送信し、ユーザーはTodo更新ページを表示できます。
djangoの各アプリの役割
Todoアプリの機能ごとに、djangoのアプリを用意しています。
アプリ名 | 概要 |
common | ・Todoアプリで使用するモデル(データ)を定義する ・Todoアプリで使用するformタグの詳細を定義する |
todolist | ・登録したTodoの一覧を表示する |
tododetail | ・登録したTodoの詳細を表示する |
todoupdate | ・登録したTodoの内容を更新する |
tododelete | ・登録したTodoを削除する |
todocreate | ・Todoを登録する |
更新/新規作成するファイル
Todoアプリを作成するために更新、新規作成したファイルの一覧です。
フォルダ名 | ファイル名 | 更新/新規作成 | コードの概要 |
todo_project | urls.py | 更新 | ・httpリクエストのルーティングを設定 ・リダイレクトの設定 |
settings.p | 更新 | ・INSTALLED_APPSにアプリを登録 ・TEMPLATESにBASE_DIRを設定 |
|
common | models.py | 更新 | ・タイトル、作業内容、優先度、期日を設定 ・優先度の選択は高、通常、低の3つ |
forms.py | 新規作成 | ・作業内容の入力フォーム表示は5行 ・優先度の選択はプルダウン ・期日の選択はカレンダー |
|
todolist | urls.py | 新規作成 | ・views.py内のTodoListTopを呼び出す |
views.py | 更新 | ・TodoListTopクラスの設定 ・template_nameとmodelを設定 |
|
tododetail | urls.py | 新規作成 | ・views.py内のTodoDetailを呼び出す |
views.py | 更新 | ・TodoDetailクラスを設定 ・template_nameとmodelを設定 |
|
todoupdate | urls.py | 新規作成 | ・views.py内のTodoUpdateを呼び出す |
views.py | 更新 | ・TodoUpdateクラスを設定 ・template_nameとmodelを設定 ・使用する入力フォームの設定 ・更新に成功したときの遷移先の設定 |
|
tododelete | urls.py | 新規作成 | ・views.py内のTodoDetailを呼び出す |
views.py | 更新 | ・TodoDetailクラスを設定 ・削除に成功したときの遷移先の設定 |
|
todocreate | urls.py | 新規作成 | ・views.py内のTodoCreateを呼び出す |
views.py | 更新 | ・TodoCreateクラスを設定 ・template_nameとmodelを設定 ・使用する入力フォームの設定 ・更新に成功したときの遷移先の設定 |
|
templates | _form.html | 新規作成 | ・作成、更新の入力フォームを定義 |
base.html | 新規作成 | ・全てのページのベースとなるhtml ・bootstrap5.3を読み込んでいる |
|
create.html | 新規作成 | ・作成のページ | |
detail.html | 新規作成 | ・詳細のページ | |
list.html | 新規作成 | ・一覧のページ | |
update.html | 新規作成 | ・更新のページ |
開発環境の用意
開発環境はVisual Studio Codeを使用します。djangoの実行環境はWindows上で動作させたUbuntuで実行します。WindowsにUbuntu環境を構築する手順は下記を参照してください。
- Pythonの実行環境を構築済みの場合は、下記を実施する必要はありません。
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install python3.12
$ sudo apt install python3.12-venv
- djangoを実行する仮想環境を作成します。
$ mkdir todo
$ cd todo
$ python3.12 -m venv venv
- django4.2.9をインストールします。
$ source ./venv/bin/active
(venv)$ pip install --upgrade pip
(venv)$ pip install django==4.2.9
- Todoアプリのプロジェクト、アプリを作成します。
(venv)$ django-admin startproject todo_project .
(venv)$ python manage.py startapp todolist
(venv)$ python manage.py startapp tododetail
(venv)$ python manage.py startapp common
(venv)$ python manage.py startapp todoupdate
(venv)$ python manage.py startapp tododelete
(venv)$ python manage.py startapp todocreate
- Todoアプリで使用するディレクトリ、ファイルを作成します。
(venv)$ mkdir templates
(venv)$ touch ./common/forms.py
(venv)$ touch ./todolist/urls.py
(venv)$ touch ./tododetail/urls.py
(venv)$ touch ./tododelete/urls.py
(venv)$ touch ./todocreate/urls.py
(venv)$ touch ./todoupdate/urls.py
(venv)$ touch ./templates/_form.html
(venv)$ touch ./templates/base.html
(venv)$ touch ./templates/create.html
(venv)$ touch ./templates/detail.html
(venv)$ touch ./templates/list.html
(venv)$ touch ./templates/update.html
- 開発環境の構築を終えると、下記のファイル・ディレクトリ構成となります。
(venv)$ cd ..
(venv)$ tree -L 3
.
└── todoapp
├── LICENSE
├── README.md
├── common
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── forms.py
├── manage.py
├── templates
│ ├── _form.html
│ ├── base.html
│ ├── create.html
│ ├── detail.html
│ ├── list.html
│ └── update.html
├── todo_project
│ ├── __init__.py
│ ├── __pycache__
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── todocreate
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── tododelete
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── tododetail
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── todolist
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── todoupdate
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
└── venv
├── bin
├── include
├── lib
├── lib64 -> lib
└── pyvenv.cfg
todo_project配下のファイル編集
todo_projectのsettings.pyを編集
- プロジェクト(todo_todoprojectディレクトリ内)のsettings.pyに以下を追加してプロジェクトに「common,todolist,tododetail,todoupdate,tododelete,todocreate」アプリを追加したことを設定します。
- settings.pyを編集し、33行目あたりにある「INSTALLED_APPS」の箇所に「’common’,’todolist’,’tododetail’,’todoupdate’,’tododelete’,’todocreate’」を追記します。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'common',
'todolist',
'tododetail',
'todoupdate',
'tododelete',
'todocreate',
]
- テンプレートhtmlを配置している場所について、BASE_DIRで設定します。
- settings.pyを編集し、57行目あたりにある「TEMPLATES」の箇所の「’DIRS’」に「[BASE_DIR / ‘templates’]」を記載します。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
todo_projectのurls.pyを編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。
- 「http://127.0.0.1:8000/admin」であった場合、djangoの管理者ページを表示する
- 「http://127.0.0.1:8000/list/」であった場合、todolist(登録したTodoの一覧)のurls.pyにリクエストを投げる
- 「http://127.0.0.1:8000/」であった場合、「http://127.0.0.1:8000/list/top/」にリダイレクトする
- 「http://127.0.0.1:8000/detail/」であった場合、tododetail(登録したTodoの詳細)のurls.pyにリクエストを投げる
- 「http://127.0.0.1:8000/create/」であった場合、todocreate(Todoの登録)のurls.pyにリクエストを投げる
- 「http://127.0.0.1:8000/update/」であった場合、todoupdate(登録したTodoの更新)のurls.pyにリクエストを投げる
上記の内容をurls.pyに記載します。
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import RedirectView
urlpatterns = [
path('admin/', admin.site.urls),
path('list/', include('todolist.urls')),
path('', RedirectView.as_view(url='/list/top/', permanent=True)),
path('detail/', include('tododetail.urls')),
path('create/', include('todocreate.urls')),
path('update/', include('todoupdate.urls')),
]
common配下のファイル編集
- commonアプリでは、複数の他のアプリケーション間で共有される機能やモデルを保持します。
commonのmodels.pyを編集
<models.pyで設定する内容>
項目 | 変数名 | フィールド | オプション | 補足 |
タイトル | title | CharField | 入力可能文字数:100 | ー |
作業内容 | description | TextField | 無し | ー |
優先度 | priority | CharField | 入力可能文字数:10 優先度:高、通常、低 デフォルト優先度:通常 |
優先度はPriorityクラスで設定 |
期限 | duedate | DateField | 無し | ー |
from django.db import models
class Priority(models.TextChoices):
HIGH = 'danger', '高'
NORMAL = 'warning', '通常'
LOW = 'primary', '低'
class TodoModel(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
priority = models.CharField(
max_length=10,
choices=Priority.choices,
default=Priority.NORMAL
)
duedate = models.DateField()
def __str__(self):
return self.title
commonのadmin.pyを編集
- 管理者ページで管理するモデルを登録します。
from django.contrib import admin
from .models import TodoModel
admin.site.register(TodoModel)
commonのforms.pyを編集
- Todoの登録/更新ページで使用するフォームの行数/プルダウン/日付を設定します。
from django import forms
from .models import TodoModel
class TodoModelForm(forms.ModelForm):
class Meta:
model = TodoModel
fields = ('title', 'description', 'priority', 'duedate')
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
'priority': forms.Select(attrs={'class': 'form-select'}),
'duedate': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
}
todolist配下のファイル編集
todolistのurls.pyを編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。「http://127.0.0.1:8000/list/top/」であった場合、todoの一覧ページを表示する
上記の内容をurls.pyに記載します。
from django.urls import path, include
from .views import TodoListTop
urlpatterns = [
path('top/', TodoListTop.as_view(), name='list')
]
todolistのviews.pyを編集
- commonアプリのTodoModelを一覧表示するためのビューを定義します。
- TodoListTopクラスはListViewを継承しています。
- TodoModelのオブジェクトリストをlist.htmlテンプレートに渡し、登録したTodoを表示するためのビューを作成しています。
- template_nameには、ビューで使用するテンプレートの名前を指定しています。
- modelには、表示するオブジェクトのリストを提供するモデルについて指定しています。
from django.shortcuts import render
from django.views.generic import ListView
from common.models import TodoModel
class TodoListTop(ListView):
template_name = 'list.html'
model = TodoModel
tododetail配下のファイル編集
tododetailのurls.pyの編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。「http://127.0.0.1:8000/detail/(プライマリキー)/」であった場合、プライマリキーに該当するtodoの詳細ページを表示する
上記の内容をurls.pyに記載します。
from django.urls import path, include
from .views import TodoDetail
urlpatterns = [
path('<int:pk>/', TodoDetail.as_view(), name='detail')
]
- 「<int:pk>/」URLからキャプチャされた整数値をpkという名前のキーワード引数としてビューに渡します。
- 通常、pk(プライマリキー)はデータベースのレコードを一意に識別するために使います。
- pk(プライマリキー)には、/1/や/2/の数字が入ります。
- それぞれの数字はレコードのIDとして扱います。
tododetailのviews.pyの編集
- commonアプリのTodoModelを一覧表示するためのビューを定義します。
- TodoDetailクラスはDetailViewを継承しています。
- TodoModelのオブジェクトリストをdetail.htmlテンプレートに渡し、登録したTodoの詳細を表示するためのビューを作成しています。
- template_nameには、ビューで使用されるテンプレートの名前を指定しています。
- modelには、表示するオブジェクトのリストを提供するモデルについて指定しています。
from django.shortcuts import render
from django.views.generic import DetailView
from common.models import TodoModel
class TodoDetail(DetailView):
template_name = 'detail.html'
model = TodoModel
todoupdate配下のファイル編集
todoupdateのurls.pyの編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。「http://127.0.0.1:8000/update/(プライマリキー)/」であった場合、プライマリキーに該当するtodoの更新ページを表示する
上記の内容をurls.pyに記載します。
from django.urls import path, include
from .views import TodoUpdate
urlpatterns = [
path('<int:pk>/', TodoUpdate.as_view(), name='update')
]
- 「<int:pk>/」URLからキャプチャされた整数値をpkという名前のキーワード引数としてビューに渡します。
- 通常、pk(プライマリキー)はデータベースのレコードを一意に識別するために使います。
- pk(プライマリキー)には、/1/や/2/の数字が入ります。
- それぞれの数字はレコードのIDとして扱います。
todoupdateのviews.pyの編集
- commonアプリのTodoModelを一覧表示するためのビューを定義します。
- TodoUpdateクラスはUpdateViewを継承しています。
- TodoModelのオブジェクトリストをupdate.htmlテンプレートに渡し、登録したTodoの詳細を表示するためのビューを作成しています。
- template_nameには、ビューで使用されるテンプレートの名前を指定しています。
- modelには、表示するオブジェクトのリストを提供するモデルについて指定しています。
- form_classには、入力フォーム設定の読み込み先を指定します。
- success_urlには、「更新」に成功したら表示するページを指定しています。
from django.shortcuts import render
from django.views.generic import UpdateView
from common.forms import TodoModelForm
from common.models import TodoModel
from django.urls import reverse_lazy
class TodoUpdate(UpdateView):
template_name = 'update.html'
model = TodoModel
form_class = TodoModelForm
success_url = reverse_lazy('list')
tododelete配下のファイル編集
tododeleteのurls.pyの編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。「http://127.0.0.1:8000/delete/(プライマリキー)/」であった場合、プライマリキーに該当するtodoを削除する
上記の内容をurls.pyに記載します。
from django.urls import path, include
from .views import TodoDelete
urlpatterns = [
path('<int:pk>/', TodoDelete.as_view(), name='delete')
]
- 「<int:pk>/」URLからキャプチャされた整数値をpkという名前のキーワード引数としてビューに渡します。
- 通常、pk(プライマリキー)はデータベースのレコードを一意に識別するために使います。
- pk(プライマリキー)には、/1/や/2/の数字が入ります。
- それぞれの数字はレコードのIDとして扱います。
tododeleteのviews.pyの編集
- commonアプリのTodoModelを一覧表示するためのビューを定義します。
- TodoDeleteクラスはDeleteViewを継承しています。
- modelには、削除するオブジェクトのリストを提供するモデルについて指定しています。
- success_urlには、「削除」に成功したら表示するページを指定しています。
from django.shortcuts import render
from django.views.generic import DeleteView
from common.models import TodoModel
from django.urls import reverse_lazy
class TodoDelete(DeleteView):
model = TodoModel
success_url = reverse_lazy('list')
todocreate配下のファイル編集
todocreateのurls.pyの編集
- HTTPリクエストオブジェクトのURLパターンに応じたviewの設定を行います。
- 記載するURLパターンは下記です。「http://127.0.0.1:8000/create/top/」であった場合、todoの作成ページを表示する
上記の内容をurls.pyに記載します。
from django.urls import path, include
from .views import TodoCreate
urlpatterns = [
path('top/', TodoCreate.as_view(), name='create')
]
todoupdateのviews.pyの編集
- commonアプリのTodoModelを一覧表示するためのビューを定義します。
- TodoUpdateクラスはUpdateViewを継承しています。
- TodoModelのオブジェクトリストをupdate.htmlテンプレートに渡し、登録したTodoの詳細を表示するためのビューを作成しています。
- template_nameには、ビューで使用されるテンプレートの名前を指定しています。
- modelには、表示するオブジェクトのリストを提供するモデルについて指定しています。
- form_classには、入力フォーム設定の読み込み先を指定します。
- success_urlには、「作成」に成功したら表示するページを指定しています。
from django.shortcuts import render
from django.views.generic import CreateView
from common.models import TodoModel
from common.forms import TodoModelForm
from django.urls import reverse_lazy
class TodoCreate(CreateView):
template_name = 'create.html'
model = TodoModel
form_class = TodoModelForm
success_url = reverse_lazy('list')
templates配下のファイル編集
base.htmlの編集
- 全htmlのテンプレートとなるhtmlファイルです。
- CSSフレームワークとしてbootstrap5.3.0を使用します。
- base.htmlに記載しているhtml基本構造タグ
<head>,<body>,<script> - base.htmlに記載しているdjangoテンプレートタグ
{% block header %}、 {% block content %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Todo 管理</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<div class="bg-body-tertiary p-3 p-sm-3 mb-2">
<div class="container">
<h2 class="display-4">{% block header %}{% endblock header %}</h2>
</div>
</div>
{% block content %}
{% endblock content %}
<!-- 共通の削除モーダル -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">削除の確認</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p id="deleteItemName">このアイテムを本当に削除しますか?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button>
<button type="button" class="btn btn-danger" id="deleteConfirmButton">削除</button>
</div>
</div>
</div>
</div>
<!-- 共通のJavaScript -->
<script>
function setupDeleteModal(itemId, itemName) {
document.getElementById('deleteItemName').textContent = '「' + itemName + '」を本当に削除しますか?';
var deleteButton = document.getElementById('deleteConfirmButton');
deleteButton.onclick = function() {
document.getElementById('deleteForm' + itemId).submit();
};
}
</script>
</body>
</html>
list.htmlの編集
- djangoテンプレート構造の解説
タグ | 解説 |
{% extends ‘base.html’ %} | base.htmlを継承する。 |
{% block header %}…{% endblock header %} | base.html 内の header ブロックを上書きする。ページのタイトルとして “Todo 一覧” を設定している。 |
{% block content %}…{% endblock content %} | テンプレートのメインコンテンツ部分です。base.html の content ブロックを上書きする。 |
- 動的コンテンツ表示の解説
タグ | 解説 |
{% for item in object_list %}…{% endfor %} | object_listはビューから渡されるmodelのオブジェクト。 forループで、object_listの各オブジェクトに対して反復処理を行う。ここでは、Todoの各項目を表示する。 |
<div class=”alert alert-{{ item.priority }}”…> | 各Todoの優先度に応じて背景色を変える。 |
{{ item.title }} | 各Todoのタイトル。 |
{{ item.duedate|date:”o/n/j” }} | 各Todoの期日。|date:”o/n/j” は日付を特定の形式で表示するためのフィルタ。 |
- ボタン・フォームの解説
タグ | 解説 |
<a class=”btn btn-warning mb-2″…> | “作成”ラベルのボタンを表示する。 |
<a class=”btn btn-primary”…> | “詳細”ラベルのボタンを表示する。 |
href=”{% url ‘detail’ item.pk %}” | ‘detail’はtododetailのurls.pyのnameで設定した値。 item.pk は対象となる詳細のプライマリキー。 |
<a class=”btn btn-success”…> | “編集”ラベルのボタンを表示する。 |
<button class=”btn btn-secondary”…> | “削除”ラベルのボタンを表示する。JavaScript関数 setupDeleteModal を呼び出し、削除を確認するモーダルウィンドウを表示する。 |
<form id=”deleteForm{{ item.pk }}”…> | 削除操作を行うための隠しフォーム。実際の削除は、このフォームをサブミットすることで行わる。 |
{% extends 'base.html' %}
{% block header %}Todo 一覧{% endblock header %}
{% block content %}
<div class="container">
<a class="btn btn-warning mb-2" href="{% url 'create' %}" role="button">作成</a>
{% for item in object_list %}
<div class="alert alert-{{ item.priority }}" role="alert">
<p>{{ item.title }} 【期日:{{ item.duedate|date:"o/n/j" }}】</p>
<a class="btn btn-primary" href="{% url 'detail' item.pk %}" role="button">詳細</a>
<a class="btn btn-success" href="{% url 'update' item.pk %}" role="button">編集</a>
<button class="btn btn-secondary" onclick="setupDeleteModal({{ item.pk }}, '{{ item.title }}')" data-bs-toggle="modal" data-bs-target="#deleteModal">削除</button>
<form id="deleteForm{{ item.pk }}" action="{% url 'delete' item.pk %}" method="POST" style="display: none;">
{% csrf_token %}
</form>
</div>
{% endfor %}
</div>
{% endblock content %}
detail.htmlの編集
- djangoテンプレート構造の解説
タグ | 解説 |
{% extends ‘base.html’ %} | base.htmlを継承する。 |
{% block header %}…{% endblock header %} | base.html 内の header ブロックを上書きする。ページのタイトルとして “Todo 詳細” を設定している。 |
{% block content %}…{% endblock content %} | テンプレートのメインコンテンツ部分です。base.html の content ブロックを上書きする。 |
- 動的コンテンツ表示の解説
タグ | 解説 |
{{ object.title }} | objectはビューから渡されるmodelのオブジェクト。 Todoのタイトル。 |
{{ object.description|linebreaksbr }} | Todoの説明。「|linebreaksbr」は改行を <br> タグに変換するフィルタ。 |
{% if %}…{% endif %} | 条件に基づいて異なる内容を表示する。Todoの優先度に応じて「高」「通常」「低」と表示する。 |
{{ item.duedate|date:”o/n/j” }} | 各Todoの期日。|date:”o/n/j” は日付を特定の形式で表示するためのフィルタ。 |
- ボタン・フォームの解説
タグ | 解説 |
<a class=”btn btn-info”…> | “Todo一覧”ラベルのボタンを表示する。 |
<a class=”btn btn-success”…> | “編集”ラベルのボタンを表示する。 |
<button class=”btn btn-secondary”…> | “削除”ラベルのボタンを表示する。JavaScript関数 setupDeleteModal を呼び出し、削除を確認するモーダルウィンドウを表示する。 |
<form id=”deleteForm{{ item.pk }}”…> | 削除操作を行うための隠しフォーム。実際の削除は、このフォームをサブミットすることで行わる。 |
{% extends 'base.html' %}
{% block header %}Todo 詳細{% endblock header %}
{% block content %}
<div class="container">
<table class="table table-striped-columns">
<tr>
<th>タイトル</th>
<td>{{ object.title }}</td>
</tr>
<tr>
<th>作業内容</th>
<td>{{ object.description|linebreaksbr }}</td>
</tr>
<tr>
<th>優先度</th>
<td>
{% if object.priority == 'danger' %}
高
{% elif object.priority == 'warning' %}
通常
{% elif object.priority == 'primary' %}
低
{% else %}
{{ object.priority }}
{% endif %}
</td>
</tr>
<tr>
<th>期限</th>
<td>{{ object.duedate|date:"o/n/j" }}</td>
</tr>
</table>
<a class="btn btn-success" href="{% url 'update' object.pk %}" role="button">編集</a>
<button class="btn btn-secondary" onclick="setupDeleteModal({{ object.pk }}, '{{ object.title }}')" data-bs-toggle="modal" data-bs-target="#deleteModal">削除</button>
<form id="deleteForm{{ object.pk }}" action="{% url 'delete' object.pk %}" method="POST" style="display: none;">
{% csrf_token %}
</form>
<a class="btn btn-info" href="{% url 'list' %}" role="button">Todo一覧</a>
</div>
{% endblock content %}
_form.htmlの編集
- create.htmlとupdate.htmlで表示する入力フォームのテンプレート
- 動的コンテンツ表示の解説
タグ | 解説 |
{{ form.title }} | Todoのタイトル。 |
{{ form.description }} | Todoの説明。 |
{{ form.priority }} | Todoの優先度。 |
{{ form.duedate }} | Todoの期限。 |
{{ submit_button_label }} | 「作成」「更新」のいずれかが入る。 入る内容は「_form.html」の呼び出し元で制御している。 |
- ボタン・フォームの解説
タグ | 解説 |
<button type=”submit” class=”btn btn-warning”>{{ submit_button_label }}</button> | 「作成」あるいは「削除」のボタンを表示する。 |
<label for=”id_title” …</label> | Todoのタイトル入力フォーム。 |
<label for=”id_description” …</label> | Todoの作業内容入力フォーム。 |
<label for=”id_priority” …</label> | Todoの優先度入力フォーム。 |
<label for=”id_duedate” …</label> | Todoの期日入力フォーム。 |
<form action="" method="POST" class="row g-3">
{% csrf_token %}
<div class="col-12 mb-2">
<label for="id_title" class="form-label">タイトル</label>
{{ form.title }}
</div>
<div class="col-12 mb-2">
<label for="id_description" class="form-label">作業内容</label>
{{ form.description }}
</div>
<div class="col-12 mb-2">
<label for="id_priority" class="form-label">優先度</label>
{{ form.priority }}
</div>
<div class="col-12 mb-2">
<label for="id_duedate" class="form-label">期日</label>
{{ form.duedate }}
</div>
<div class="col-12">
<button type="submit" class="btn btn-warning">{{ submit_button_label }}</button>
<a class="btn btn-info" href="{% url 'list' %}" role="button">Todo一覧</a>
</div>
</form>
create.htmlの編集
- djangoテンプレート構造の解説
タグ | 解説 |
{% extends ‘base.html’ %} | base.htmlを継承する。 |
{% block header %}…{% endblock header %} | base.html 内の header ブロックを上書きする。ページのタイトルとして “Todo 作成” を設定している。 |
{% block content %}…{% endblock content %} | テンプレートのメインコンテンツ部分。base.html の content ブロックを上書きする。 |
{% include ‘_form.html’ with submit_button_label=’作成’ %} | _form.htmlを読み込む際、submit_button_labelを”作成”に設定している。 |
{% block header %}Todo 作成{% endblock header %}
{% block content %}
<div class="container">
{% include '_form.html' with submit_button_label='作成' %}
</div>
{% endblock content %}
update.htmlの編集
- djangoテンプレート構造の解説
タグ | 解説 |
{% extends ‘base.html’ %} | base.htmlを継承する。 |
{% block header %}…{% endblock header %} | base.html 内の header ブロックを上書きする。ページのタイトルとして “Todo 編集” を設定している。 |
{% block content %}…{% endblock content %} | テンプレートのメインコンテンツ部分。base.html の content ブロックを上書きする。 |
{% include ‘_form.html’ with submit_button_label=’作成’ %} | _form.htmlを読み込む際、submit_button_labelを”更新”に設定している。 |
{% extends 'base.html' %}
{% block header %}Todo 編集{% endblock header %}
{% block content %}
<div class="container">
{% include '_form.html' with submit_button_label='更新' %}
</div>
{% endblock content %}
Todoアプリの起動
- Todoアプリを起動する前に、commonで設定したmodels.pyの内容でデータベースを構築します。
- 下記の実行後、models.pyの変更がなければ、次回からは実行不要です。
(venv)$ python manage.py makemigrations
(venv)$ python manage.py migrate
- Todoアプリを起動します。
(venv)$ python manage.py runserver
- 下記のURLにアクセスすると、Todoアプリに接続できます。
「http://127.0.0.1:8000/」
以上でTodoアプリの構築は完了です。
コメント