ブートストラップ等を導入して見た目を整えていく
urls.py
from django.urls import path
from .views import TodoList
urlpatterns = [
path('list/', TodoList.as_view()),
path('detail/', TodoDetail.as_view()),
]
views.py
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
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を作成する
{{ object.title }}
{{ object.memo }}
起動してみる
python3 manage.py runserver


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

list.htmlにテンプレートをコピペする
<!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にも同樣にする
<!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を整える
<!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を作成する
{% block header %}
{% endblock header %}
list.htmlを更新する
{% extends 'base.html' %}
{% comment %} このファイルはbase.htmlを基準として作成するという宣言 {% endcomment %}
{% block header%}
これがヘッダーです
{% endblock %}
さらにbase.htmlを更新=Bootstrapスターターテンプレートをコピペして、bodyタグ内に追記する
<!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をさらに更新する
{% 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コンポーネントからコピペ
{% 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 %}
サーバーを起動して確かめる
python3 manage.py runserver

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

まずはタイトル部分から
ジャンボトロンを使う
{% 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を更に更新。リストをコンテナ化する
{% 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タグで生成されたボタンが良い
{% 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 %}

完成形に近づいてきました。
タスクの属性に応じてコンテナの色が変わるようにします
{% 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も仕込む
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する
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
というファイルが作られる。
中身を見てみると
# 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する
python3 manage.py migrate
めでたくデータベースへの反映も完了した

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

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

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