このチャプターでは、フォルダ一覧ページを作成していきます!
##記事一覧
DjangoでTodoアプリを作る①Dockerで環境を構築する
DjangoでTodoアプリを作る②フォルダ一覧ページの作成
DjangoでTodoアプリを作る③タスク一覧ページの作成
DjangoでTodoアプリを作る④フォルダー、タスク作成機能の実装
DjangoでTodoアプリを作る⑤タスク編集機能の作成
#URLの設定
フォルダー一覧ページの設計は以下の通り。
URL | 処理 |
---|---|
/foleders/{フォルダのID}/tasks | フォルダー一覧ページを表示する |
この設計を踏まえて、django_todo/urls.py
、todo/urls.py
を編集していきます。
##django_todo/urls.py
まず、include関数を使いたいので、from django.urls…
の行を変更し、インポートを追加します。そして、todo.urls
をインポートする行を追加します。結果、django_todo/urls.py
は以下のようになります。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('folders/', include('todo.urls')),
]
urlが'folders/'だった場合は、todo/urls.py
を参照しなされという意味です。
そのtodo/urls.py
は次のように定義します。
##todo/urls.py
todo
ディレクトリの下に、新しく urls.py
という空のファイルを作ります。
$ touch todo/urls.py
作成した、todo/urls.py
を以下のように編集します。
from django.urls import path
from . import views
urlpatterns = [
path('<int:id>/tasks', views.index, name='tasks.index'),
]
最初の2行は、Djangoの path 関数と、todoの全ての ビュー(今は1つもありません。これから作っていきます!)をインポートするという意味です。
アドレスの文字列の部分にある< int:id >が引数の型と名称を指定しています。その結果、この部分に現れるint型の値が、idという名前で取得され,対応するview関数(ここでは、view.pyのindex関数)に引数として渡されます。
urlpatterns = ...
の部分において、folders/の下に< int:id >/tasks
がある、つまり、folders/< 整数 >/tasks
というアドレスが来ると、view.pyのindex関数を呼び出すという処理をします。
name=
では、このURLパターンに名前をつけています。
#モデルの定義
folderテーブルの定義は以下のようにします。
カラム論理名 | カラム物理名 |
---|---|
ID | id |
タイトル | title |
作成日 | created_at |
このテーブル定義をもとに、todo/models.py
を編集していきます。
from django.conf import settings
from django.db import models
from django.utils import timezone
class Folder(models.Model):
title = models.CharField(max_length=20)
created_at = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
idについての記述がありませんが、Djangoでは自動的に定義されます。詳細は、モデル |Djangoドキュメントが詳しいです。
定義したフィールドの内容は以下の通りです。
フィールド | どんなフィールドか |
---|---|
models.CharField | 文字数が制限されたテキストを定義するフィールド |
models.DateTimeField | – 日付と時間のフィールド |
__str__関数では、管理画面などで表示される文字列を定義しています。(models.pyに記述されたdef __str__(self)とは?)
#view関数の定義
todo.py
にビューを記述していきます。
以下のように編集してください。
from django.shortcuts import render
from django.utils import timezone
from .models import Folder
def index(request, id):
folders = Folder.objects.filter(created_at__lte=timezone.now()).order_by('created_at')
return render(request, 'index.html', {'folders':folders})
一行目でrender関数をインポートしています。
二行目では、models.py
で定義したFolder
モデルをインポートしています。
render関数では、第一引数にrequest、第二引数にテンプレートファイル名を記述しています。
第3引数では、テンプレートに渡すデータについて記述しています。renderの第3引数に辞書を渡すことでtemplateに値を渡すことができます。
template内で渡された値を使う場合は{{ folders }}の形式で書きます。
※「render」は、「与える」、「差し出す」といった意味を持った英単語。requestやfoldersをindex.htmlに「差し出す」という意味で捉えるとわかりやすそう。
#templateの作成
テンプレートとはアプリケーションがレスポンスする HTML の雛形で、制御構文(if や foreach など)や変数の展開を記述することができます。ページの枠組みだけ用意して、URL に応じて変わる箇所だけが穴埋めになっているイメージ。
以下のコマンドでtodo
ディレクトリにtemplates
ディレクトリを作成し、その中にindex.html
を作成します。
$ mkdir todo/templates
$ touch todo/templates/index.html
index.html
は以下のように編集してください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Todo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootflat/2.0.4/css/bootflat.min.css">
</head>
<body>
<header>
<nav class="my-navbar">
<a class="my-navbar-brand" href="folders/1/tasks">Todo</a>
</nav>
</header>
<main>
<div class="container">
<div class="row">
<div class="col col-md-4">
<nav class="panel panel-default">
<div class="panel-heading">フォルダー</div>
<div class="list-group">
{% for folder in folders %}
<a
href="{% url 'tasks.index' id=folder.id %}"
class="list-group-item {% if current_folder_id == folder.id %}active{% endif %}"
>
{{ folder.title }}
</a>
{% endfor %}
</div>
<div class="panel-body">
<a href="#" class="btn btn-default btn-block">
フォルダーを追加する
</a>
</div>
</nav>
</div>
<div class="column col-md-8">
<!-- タスクはここに表示される -->
</div>
</div>
</div>
</main>
</body>
</html>
head部分についてはHTML5のhead内の記述が詳しいです。
上記のhtmlの記述の中で、注目すべきところは以下の部分。
{% for folder in folders %}
<a
href="{% url 'tasks.index' id=folder.id %}",
class="list-group-item {% if current_folder_id == folder.id %}active{% endif %}"
>
{{ folder.title }}
</a>
{% endfor %}
テンプレートの中では、{% %}で囲むことによってpythonのようにfor文を使用することができます。
href = ... では、todo/urls.py
の path() 関数の name 引数を定義していた(ここでは、tasks.index
)ので、テンプレートタグの {%url%}
を使用してリンク先を表しています。
class="list-group-item {% if current_folder_id == folder.id %}active{% endif %}"
この部分では、現在選択されているフォルダのIDをactiveに設定しています。
#CSSの作成
まず、以下のようなディレクトリ構成になるようにtodoディレクトリ配下にstaticディレクトリ、cssディレクトリ、style.cssファイルを作成します。
todo
├── static
│ └── css
└── style.css
style.cssは以下のように記述します。
body {
background-color: #b4e7cf;
}
.navbar {
margin: 2rem 0 2.5rem 0;
}
.my-navbar {
align-items: center;
background: #474a2c;
display: flex;
height: 6rem;
justify-content: space-between;
padding: 0 2%;
margin-bottom: 3rem;
}
.my-navbar-brand {
font-size: 20px;
}
.my-navbar-brand,
.my-navbar-item {
color: #b4e7cf;
}
.my-navbar-brand:hover,
a.my-navbar-item:hover {
color: #ffffff;
}
.panel-default>.panel-heading {
color: #474a2c;
background-color: #9bdeac;
border-color: #e6e9ed;
}
a.list-group-item:hover {
color: #fff;
background-color: #474a;
}
a.list-group-item.active,
a.list-group-item.active:focus,
a.list-group-item.active:hover{
color: #fff;
background-color: #474a;
border-color: #e6e9ed;
}
a {
color: #474a;
text-decoration: none;
}
a:hover{
color: #4909;
}
.btn-default:hover {
color: #fff;
background-color: #474a;
}
.btn{
border-color: #474a;
}
.btn-primary {
background-color: #474a;
border-color: #474a;
}
.btn-primary:hover {
background-color: #4909;
}
.table td:nth-child(2),
.table td:nth-child(3),
.table td:nth-child(4) {
white-space: nowrap;
width: 1px;
}
.form-control[disabled],
.form-control[readonly] {
background-color: #fff;
}
index.html
にCSSを読み込ませるため、index.htmlを編集します。
1行目に以下を追加してください。
{% load static %}
head
部分に以下を追加してください。
<link rel="stylesheet" href="{% static 'css/style.css' %}">
#マイグレーション
次のコマンドでマイグレーションファイルを作成します。以下のようになればOKです。
$ docker-compose run web python3 manage.py makemigrations
Starting django_todo_db_1 ... done
Migrations for 'todo':
todo/migrations/0001_initial.py
- Create model Folder
コマンド実行後、以下のようなマイグレーションファイルが作成されます。
# Generated by Django 2.2.12 on 2020-04-16 22:22
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Folder',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=20)),
('created_at', models.DateTimeField(default=django.utils.timezone.now)),
],
),
]
このファイルをマイグレートすることによって、データベースを作成することができます。
$ docker-compose run web python3 manage.py migrate
Starting django_todo_db_1 ... done
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, todo
Running migrations:
Applying todo.0001_initial... OK
#adminページの作成
作成したFolderクラスにおいて追加、編集、削除するのにDjango adminを使います。
todo/admin.py
ファイルを、内容を次のように編集してください。
from django.contrib import admin
from .models import Folder
admin.site.register(Folder)
先ほど定義したFolderモデルをimportしています。 また、モデルをAdminページ(管理画面)上で見えるようにするため、admin.site.register(Folder)でモデルを登録しています。
そして、http://localhost:8000/admin/ にアクセスしてみてください。
次のようなログインページが表示されます。
ログインするには、superuser (サイトの全てを管理するユーザー)を作る必要があります。
以下のコマンドでsuperuserを作成します。
$ docker-compose run web python3 manage.py createsuperuser
ユーザーネーム、メールアドレス、パスワードを入力していき、
Superuser created successfully.
となればユーザーの作成が完了です。
adminページに戻り、ログインすると以下のようなページが表示されます。
Foldersの、「追加」をクリックすると次のページが出てくるはずです。
なんでもよいので、2,3個folderを追加しておきましょう。ぼくは、「プログラミング」、「大学の課題」、「その他」を追加しておきました
次のコマンドでデータが挿入されていることが確認できます。詳しくはDjango ORM(クエリセット) ・Django Girls Tutorial
$ docker-compose run web python3 manage.py shell
Starting django_todo_db_1 ... done
Python 3.8.2 (default, Feb 26 2020, 14:58:38)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from todo.models import Folder
>>> Folder.objects.all()
<QuerySet [<Folder: プログラミング>, <Folder: 大学の課題>, <Folder: その他>]>
#確認
$ docker-compose up -d
でサーバーを立ち上げて、http://localhost:8000/folders/1/tasks にアクセスしてみましょう。
以下のようになっていたらOKです!
#おわりに
これでこのチャプターは終わりです!
ここまでのコードは、リポジトリのchapter2ブランチにあります。
次のチャプターではタスク一覧ページを実装していきます!
DjangoでTodoアプリを作る③タスク一覧ページの作成
##記事一覧
DjangoでTodoアプリを作る①Dockerで環境を構築する
DjangoでTodoアプリを作る②フォルダ一覧ページの作成
DjangoでTodoアプリを作る③タスク一覧ページの作成
DjangoでTodoアプリを作る④フォルダー、タスク作成機能の実装
DjangoでTodoアプリを作る⑤タスク編集機能の作成
##参考文献
Djangoで外部キー制約を記述する