ブートストラップ等を導入して見た目を整えていく
urls.py
1 2 3 4 5 6 7 |
from django.urls import path from .views import TodoList urlpatterns = [ path('list/', TodoList.as_view()), path('detail/', TodoDetail.as_view()), ] |
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from django.shortcuts import render from django.views.generic import ListView, DetailView from .models import TodoModel # Create your views here. class TodoList(ListView): template_name = 'list.html' model = TodoModel class TodoDetail(DetailView): template_name = 'detail.html' model = TodoModel |
urls.py
1 2 3 4 5 6 7 8 |
from django.urls import path from .views import TodoList, TodoDetail urlpatterns = [ path('list/', TodoList.as_view()), path('detail/<int:pk>', TodoDetail.as_view()), ] |
<ink:pk>はobjectに格納されているプライマリーキー(pk)を取得するタグ。intはiteger型という事を指す
template下にlist.htmlを作成する
1 2 3 |
{{ object.title }} {{ object.memo }} |
起動してみる
1 |
python3 manage.py runserver |


うまくいきました。
Bootstrapを導入する
ブートストラップのスターターテンプレートを引っ張ってくる

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 28 29 30 |
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> {% for item in object_list %} <ul> <li>{{ item.title }}</li> <li>{{ item.memo }}</li> </ul> {% endfor%} <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html> |
※いままで書いていたコードをbodyタグの中に入れる
detail.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 |
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> {{ object.title }} {{ object.memo }} <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html> |
Bootstrapのリファレンスを確認する
detail.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 |
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> <div class="alert alert-primary" role="alert"> {{ object.title }} </div> <div class="alert alert-primary" role="alert"> {{ object.memo }} </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html> |
http://127.0.0.1:8000/detail/1を確認

うまくいきました。
htmlファイルの重複項目(Bootstrapスターターテンプレートやレイアウト等)をまとめる:base.html
templates下にbase.htmlを作成する
1 2 |
{% block header %} {% endblock header %} |
list.htmlを更新する
1 2 3 4 5 6 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} これがヘッダーです {% endblock %} |
さらにbase.htmlを更新=Bootstrapスターターテンプレートをコピペして、bodyタグ内に追記する
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 |
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> {% block header %} {% endblock header %} {% block content %} {% endblock content %} <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html> |
list.htmlをさらに更新する
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} リストです。 {% endblock %} {% block content %} {% for item in object list %} {{ item.title }} {{ item.memo }} {% endfor %} {% endblock content %} |
list.htmlをにBootstrapを適用してみる
Bootstrapコンポーネントからコピペ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} リストです。 {% endblock %} {% block content %} {% for item in object_list %} <div class="alert alert-secondary" role="alert"> {{ item.title }} </div> <div class="alert alert-secondary" role="alert"> {{ item.memo }} </div> {% endfor %} {% endblock content %} |
サーバーを起動して確かめる
1 |
python3 manage.py runserver |

うまくいきました。
本番環境を見据えたスタイルを作り込む
目標はこんな感じ

まずはタイトル部分から
ジャンボトロンを使う
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} <div class="jumbotron jumbotron-fluid"> <div class="container"> <h1 class="display-4">Todolist</h1> <p class="lead">TodoListを作って毎日を効率的に過ごしましょう。</p> </div> </div> {% endblock %} {% block content %} {% for item in object_list %} <div class="alert alert-secondary" role="alert"> {{ item.title }} </div> <div class="alert alert-secondary" role="alert"> {{ item.memo }} </div> {% endfor %} {% endblock content %} |
runserverで確認すると

いい感じ
list.htmlをいじる
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 28 29 30 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} <div class="jumbotron jumbotron-fluid"> <div class="container"> <h1 class="display-4">Todolist</h1> <p class="lead">TodoListを作って毎日を効率的に過ごしましょう。</p> </div> </div> {% endblock %} {% block content %} <div class='container'> {% for item in object_list %} <div class="alert alert-secondary" role="alert"> {{ item.title }} </div> <div class="alert alert-secondary" role="alert"> {{ item.memo }} </div> {% endfor %} </div> {% endblock content %} |
list.htmlを更に更新。コンテナにボタンを配置する
※djangoで開発をする際は、ボタンタグではなく、aタグで生成されたボタンが良い
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 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} <div class="jumbotron jumbotron-fluid"> <div class="container"> <h1 class="display-4">Todolist</h1> <p class="lead">TodoListを作って毎日を効率的に過ごしましょう。</p> </div> </div> {% endblock %} {% block content %} <div class='container'> {% for item in object_list %} <div class="alert alert-secondary" role="alert"> <p>{{ item.title }}</p> <a href="#" class="btn btn-info" tabindex="-1" role="button" aria-disabled="true">編集</a> <a href="#" class="btn btn-primary" tabindex="-1" role="button" aria-disabled="true">削除</a> <a href="#" class="btn btn-success" tabindex="-1" role="button" aria-disabled="true">詳細</a> </div> {% comment %} memoは、リンク先にするので削除した {% endcomment %} {% endfor %} </div> {% endblock content %} |

完成形に近づいてきました。
タスクの属性に応じてコンテナの色が変わるようにします
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 |
{% extends 'base.html' %} {% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %} {% block header%} <div class="jumbotron jumbotron-fluid"> <div class="container"> <h1 class="display-4">Todolist</h1> <p class="lead">TodoListを作って毎日を効率的に過ごしましょう。</p> </div> </div> {% endblock %} {% block content %} <div class='container'> {% for item in object_list %} <div class="alert alert-{{ item.priority }}" role="alert"> <p>{{ item.title }}</p> <a href="#" class="btn btn-info" tabindex="-1" role="button" aria-disabled="true">編集</a> <a href="#" class="btn btn-primary" tabindex="-1" role="button" aria-disabled="true">削除</a> <a href="#" class="btn btn-success" tabindex="-1" role="button" aria-disabled="true">詳細</a> </div> {% comment %} memoは、リンク先にするので削除した {% endcomment %} {% endfor %} </div> {% endblock content %} |
19行目の{{ item.priority }}を変数として使います。
item.priorityの設定をmodels.pyに仕込む
その他に期日=duedateも仕込む
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from django.db import models # Create your models here. PRIORITY = (('danger','high'),('info','normal'),('success','low')) class TodoModel(models.Model): title = models.CharField(max_length=100) memo = models.TextField() priority = models.CharField( max_length = 50, choices = PRIORITY ) duedate =models.DateField() def __str__(self): return self.title |
models.pyをいじったのでまたmakemygrationする
1 |
python3 manage.py makemigrations |
すると何か出てくる

あらたにduedateという概念が出てきたけど、今までのデータに入っていないのでnullになるよ!だからmigrationしないよ!
という意味で、duedate = model.DateField(null = true)とする事もできるが、デフォルトでnullを許容しないようになっているので、そうなっている
で、聞かれているのは
1.デフォルトの数字を入れる
2.作り直す
今回は1を選択して1つずつ数字を入れる事にする。

timezone.now
と入れると今の時間を入れるよ!と言ってきているのでそれに従う

PRIORITYについてどうするかと聞かれているので、とりあえず全部’danger’という事にする

すると新たに
todo/migrations/0002_auto_20200719_1521.py
というファイルが作られる。
中身を見てみると
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 |
# Generated by Django 3.0.8 on 2020-07-19 15:21 from django.db import migrations, models import django.utils.timezone class Migration(migrations.Migration): dependencies = [ ('todo', '0001_initial'), ] operations = [ migrations.AddField( model_name='todomodel', name='duedate', field=models.DateField(default=django.utils.timezone.now), preserve_default=False, ), migrations.AddField( model_name='todomodel', name='priority', field=models.CharField(choices=[('danger', 'high'), ('info', 'normal'), ('success', 'low')], default='danger', max_length=50), preserve_default=False, ), ] |
AddFieldとしてduedateが追加されている。
で、あらためてmigrateする
1 |
python3 manage.py migrate |
めでたくデータベースへの反映も完了した

/adminの中身の確認をしてみる
1 |
python3 manage.py runserver |

このようにPriorityとDuedateが追加されている
HTMLも確認する

一個一個のデータが反映されている事が確認できる
![]() |
![]() |
---|
コメントを残す