今回はシリーズ第1回として、TODOリストの基本的な部分を実装していきます。
TODOリストをブラウザに表示できることを目標に、取り組んでいきましょう!
この記事を読んで取り組むことで、Djangoの基本的な要素である以下を習得することができます。
- Modelsの作成方法とデータベースマイグレーション
- クラスベースビュー(ListView)の概要と使い方
- URLの設定方法
- フロントエンドライブラリのBootstrap4の使い方
DjangoでTODOリストを作ろう!その1:タスクを表示しよう
アプリのひな型を作る
まずはTODOリストのひな型を作成します。
上記で掲載した記事通りに作業している場合は以下の形に近いフォルダ構成になっているはずです。
この中に、上記の画像のように「djangotodo」というフォルダを自動生成します。
Docker-Desktopを起動した状態で以下の手順に従ってアプリのひな型を作成しましょう。
- ターミナルを開きます
- プロジェクトのルートディレクトリに移動します
- 次のコマンドを実行して、新しいアプリを作成します
1 |
docker-compose exec web python manage.py startapp djangotodo |
1 |
python manage.py startapp djangotodo |
ここまで完了したらConfigクラスをsettings.pyに追記しましょう。
djangotodoフォルダの中のapps.pyをエディタで開きます。
1 2 3 4 5 6 |
from django.apps import AppConfig class DjangotodoConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'djangotodo' |
class名の「DjangotodoConfig」をコピーして、プロジェクトのsettings.pyに貼り付けます。
1 2 3 4 |
INSTALLED_APPS = [ --省略-- 'djangotodo.apps.DjangotodoConfig' #追加 ] |
INSTALLED_APPSの末尾に追加してください。これでdjangotodoがアプリとして認識されます。
TODOリストのmodelsを作る
Djangoアプリケーションは以下のような構成で出来ています。
そのため今回はModel→Views→Templateの順で作成していきます。
作成されたdjangotodoフォルダの中には「models.py」というファイルがあるのでそれを開いて以下のように記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from django.db import models # taskというテーブルを作成します class Task(models.Model): #タスク名を定義する title = models.CharField(max_length=200) #作成日を定義する created_at = models.DateTimeField(auto_now_add=True) #期限日を定義する due_date = models.DateField(null=True, blank=True) def __str__(self): return self.title |
modelsはデータベースに対応するファイルです。
上記を簡単に説明すると、以下のようになります。
=で分割されると考えてください。左側は列名で、titleという列がデータベースに作られます。
右側はデータの情報です。この場合は文字列で、最大200文字入力できます。
データの作成日を日付時間形式で登録します。
auto_now_addがTrueなので、自動で作成した日付と時間が入ります。
タスクの期限を設定します。こちらは日付の形式です。
またタスクの期限は存在しない場合もあるのでnullとblankを許容しています。
データベースをマイグレーションする
このままではmodels.pyファイルを作成しただけですので、この変更をデータベースに通知する必要があります。
新しいテーブルを作成するために、以下の手順を踏みましょう。
1:Dockerコンテナに入るために、次のようなコマンドを入力します。
1 |
bash docker-compose exec web bash |
2:make migrattionsコマンドを実行します。
1 |
python manage.py makemigrations djangotodo |
3:migrateコマンドを実行します。
1 |
python manage.py migrate |
これで、Djangoのマイグレーションが実行され、データベースが作成されます。
DjangoのDBを作成する場合には必ずmakemigrations→migrateの順に実行するようにしてください。
TODOリストのviewsを作る
続いてviewsを作成します。
DjangoアプリにおけるViewはデータの抽出、加工を行い、Templateに渡す大事な役割を果たしています。
views.pyのファイルを開いて以下のように記入します。
1 2 3 4 5 6 7 8 9 10 11 12 |
from django.views.generic import ListView from .models import Task #ListViewを継承して作成 class TaskList(ListView): #使用するModelを指定 model = Task #使用するテンプレートファイルを指定 template_name = 'task_list.html' #コンテキスト名を設定 context_object_name = 'tasks' #データの並び順を指定 ordering = ['-created_at'] |
以下、説明です。
クラスベースビューのListViewを用いて、TODOリストのタスク表示を簡潔に実装しています。
クラスベースビューを使う際の設定内容を配下に記載していきます。
リスト表示をするデータベーステーブルをmodelsファイルから選択しています。
この場合データベースのtaskテーブルの全データが表示される形になります。
渡したデータを表示するHTML形式のテンプレートを指定します。
task_list.htmlについてはこのあとすぐ作成します。
コンテキストはデータを格納してテンプレートに渡す箱のようなものです。
この箱の名前を「tasks」と指定したので、テンプレートの中で「tasks」と記載すればデータを取り出せます。
データベースから取り出したデータの並び順を定義しています。
今回は作成した日時順に取り出しています。
また列名の先頭に「-」をつけると降順にできるので覚えておくと良いでしょう。
付けなければ昇順でデータを並べます。
ちなみにですが、複数の列を指定することも可能です。
例えば同じ作成日ですが期日が近いものを上から並べる場合は以下のようにします。
1 |
ordering = ['-created_at','due_date'] |
TODOリストのTemplateを作る
続いて最後の要素であるTemplateを作っていきます。
djangotodoのフォルダの中に「templates」というフォルダを作成し、その中に以下の2つのファイルを作成してください。
- base.html
- task_list.html
Djangoにはテンプレートを共通化する処理があり、共通部分をbase.htmlに、差分をtask_list.htmlに記載します。
例えばヘッダーやフッターは全ページで作成するのでbase.htmlに記載します。
一方でリスト表示する部分はこのページ限定なのでtask_listに記載します。
二つのHTMLには以下のように記載してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- 1.ページのタイトル設定箇所 --> <title>{% block title %} {% endblock %}</title> <!-- Bootstrap CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <!-- 2.URLはDjango形式で指定できる --> <a class="navbar-brand" href="{% url 'task_list' %}">TODO List</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> </div> </nav> <main class="container"> <!-- 3.本文の定義場所 --> {% block content %} {% endblock %} </main> </body> </html> |
base.htmlは各種ページの共通部分ですが、ページごとに異なる部分を明記する場合には上記のように指定します。
{% block %}{% endblock %}は各ページを表示するHTMLファイルで使用可能です。
この後出てきますが、リスト一覧HTMLでは以下のようにすると良いでしょう。
1 |
{% block title %}Task List{% endblock %} |
更新画面ならば「Task Update」にしますし、削除画面があるなら「Task Delete」にします。
ページごとに一部を変えたい場合に便利です。
また複数使用することもできます。その場合はtitleの部分を適度に変えてください。
例えばCSSファイルをページごとに変えたいなら以下のように指定すると良いでしょう。
1 |
{% block cssfile %}{% endblock %} |
それぞれのページでCSSファイルを定義できます。
a要素はリンクを生成するHTMLコードですが、ここに「{% url ‘task_list’ %}」という指定がなされています。
この「task_list」はurls.pyで指定する名前で、これを指定すると自動でURLを作成してくれます。
詳細はurls.pyを作成するときに説明します。
役割は上記の「1.ページのタイトル設定箇所」と同じですが、ここでは本文を定義しています。
これにより各ページでは本文の中身を記載するだけでページが表示できるようになります。
今回はTODOリストの見栄えをよくするためにbootstrapを導入しています。
Djangoの説明のためにbootstrapの詳細な説明はしませんが、上記の記載をそのままコピー&ペーストすることでおしゃれなデザインが出来上がります。
base.htmlは全ページの共通部分を扱っています。
本来ならば全ページのHTMLファイルに記載しなくてはならないbootstrapをこのファイルのみに記載すれば良いので楽です。
更に変更する場合もこのbase.htmlのみを変更すればいいので、とても効率的です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<!-- 1.base.htmlの大部分を使用し、一部の変更を以下に記す --> {% extends 'base.html' %} {% block title %}Task List{% endblock %} {% block content %} <h1>タスク一覧</h1> <table class="table"> <thead> <tr> <th>タスク</th> <th>期日</th> <th>Action</th> </tr> </thead> <tbody> <!-- 2.タスクをループ処理で表示 --> {% for task in tasks %} <tr> <td class="task_title">{{ task.title }}</td> <td class="task_due_date">{{ task.due_date | date:"Y年m月d日" }}</td> <td style="display:flex"> <button class="btn btn-primary btn-sm toggle-completed">未完了にする</button> <a href="#" class="btn btn-secondary">編集</a> <button type="submit" class="btn btn-danger">削除</button> </td> </tr> <!-- 3.データが存在しない場合 --> {% empty %} <tr> <td colspan="4">タスクがありません</td> </tr> {% endfor %} </tbody> </table> {% endblock %} |
共通部分のHTMLファイルを指定します。今回はbase.htmlですね。
Djangoで共通HTMLを使用するには以下のようにするのを覚えておきましょう。
forはプログラミングによくある文言で、反復処理を意味します。
この場合は「tasks」のデータを反復処理でループしています。
データベースのtaskテーブルのデータが展開され、taskという名前でアクセスできるようになります。
その下にある「task.title」などが分かりやすいですね。
この処理は「{% endfor %}」の部分で終了します。
for~endforまでのHTMLコードがタスク数分繰り返されることになります。
注:もしも{% for sample in tasks %}とした場合はそれぞれ記載が「sample.title」といった具合に変わります。好きなように命名できますが、なるべくわかりやすい名前を付けるのがおススメです。
データが存在しないときに表示する内容を決めています。
ここでは「タスクがありません」と表示しています。
urlsを作成して、URLルーティングを構成する
さて、ここまででModel、View、Templateが出来たわけですが、これらをurls.pyで連結していきましょう。
アプリ内のurls.pyで完結するために、プロジェクトのurls.pyに追加します。
python-docker-devenv\composeexample\urls.pyに以下のように追記しましょう。
1 2 3 4 5 6 7 8 |
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('dockermain/',include('dockermain.urls')), path('djangotodo/',include('djangotodo.urls')) #追加 ] |
includeでdjangotodoフォルダ配下のurls.pyを取得しています。
djangotodoフォルダの中にも同じ名前のurls.pyを作成して、以下のように記載します。
1 2 3 4 5 6 |
from django.urls import path from .views import TaskList urlpatterns = [ path('', TaskList.as_view(), name='task_list'), ] |
urls.pyはpathに注目し、3つの引数を正しく設定しましょう。
それぞれの設定値の詳細は以下になります。
ページを表示するURLを指定します。プロジェクトのurls.pyで「djangotodo/」までは指定されているので、その先を指定しています。
上記の例ではその先がないので、「djangotodo/」というURLにマッチするようになっています。
使用するviewを選択します。ここではTaskListを指定しています。
またクラスベースビューを使用する場合にはクラス名の後に「.as_view()」をつけてください。
このURLに対して名前を付けます。上記の例ではtask_listですね。
この名前はTemplateやViewで用いられます。
例えばbase.htmlにもありましたが、a要素のURLを作成する際に「href=”{% url ‘task_list’ %}”」とnameで指定したを渡すことでリダイレクト先のURLを決定することができます。
アクセスして、TODOリストを確認する
準備が完了したので、開発環境を起動してTODOリストを確認してみましょう。
ターミナルからdockerのコンテナに入り、以下のコマンドを入力して開発環境を立ち上げます。
1 |
python manage.py runserver |
ターミナル内にURLが表示されると思うので、それをコピーしてブラウザに貼り付けましょう。
おそらくURLは「http://127.0.0.1:8000/」になっているはずです。
「http://127.0.0.1:8000/djangotodo」にアクセスすれば、以下のような画面が表示されるはずです。
まだタスクを投入していないのでタスク一覧は表示されません。
しかし、「タスクがありません」という表記がされればTODOリスト自体の表示は上手くいっています。
おわりに
ここまでのソースはGithubに掲載しておくので、もしも見返したい場合は確認してみてください。
今回は第一歩としてリスト表示を行ったので、次の記事でタスクを追加していきましょう。
「DjangoでTODOリストを作ろう!その1」では、Djangoを使ってTODOリストのアプリケーションを作成し、タスクを表示する方法を学びました。 [sitecard subtitle=関連記事 url=https://freem[…]