todoアプリを追加する。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todo',
]
templatesフォルダが作成されていることを確認する。
todoフォルダ以下にurls.pyファイルを作成する。
urlのつなぎこみ
まずはtodoprojectのurls.pyの編集。includeを使って、
アプリにurls.pyにつなげる。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('todo.urls')),
]
models.pyの編集
CharFieldはタイトルなどの短めの文字のための型。
TextFieldは長めの文字のための型
from django.db import models
# Create your models here.
class TodoModel(models.Model):
title = models.CharField(max_length=100)
memo = models.TextField()
makemigrationsとmigrate
makemigrationsはmodels.pyとDBの中間にある生成物。
過去のDBに戻すことができる。
migrateは実際にDBにテーブルができあがる。
makemigrationsの実行
manage.py@todoproject > makemigrations
Migrations for 'todo':
todo/migrations/0001_initial.py
- Create model TodoModel
migrateの実行
manage.py@todoproject > migrate
createsuperuser
manage.py@todoproject > createsuperuser
admin.pyの編集
管理画面から直接DBにデータをセットできるようにする。
from django.contrib import admin
from .models import TodoModel
# Register your models here.
admin.site.register(TodoModel)
管理画面のデータ一覧画面の表示を変更
タイトルが表示されるようにする。
class TodoModel(models.Model):
title = models.CharField(max_length=100)
memo = models.TextField()
def __str__(self):
return self.title
djangoのテンプレートとCRUD(クラッド)
C Create(作成する)
R Read(読み込む、情報を取る)
U Update(更新する)
D Delete(削除する)
CRUDとDjangoのテンプレート
C Create(作成する)→ CreateView
R Read(読み込む、情報を取る)→ ListView,DetailView
U Update(更新する)→ UpdateView
D Delete(削除する)→ DeleteView
ListView
データの一覧をリストとして表示することに適したテンプレート
ListViewの作成
from django.urls import path
from .views import TodoList
urlpatterns = [
path('list/', TodoList.as_view()),
]
modelでmodels.pyにあるどのmodelを使用するかを指示する。
from django.shortcuts import render
from django.views.generic import ListView
from .models import TodoModel
# Create your views here.
class TodoList(ListView):
template_name = 'list.html'
model = TodoModel
object_listはDBのオブジェクトが入っている。
{% for post in object_list %}
{{ post.title }}
{{ post.memo }}
{% endfor %}
DatailView
データの中身を表示することに適したテンプレート
int:pkとはinteger型のプライマリーキーのこと。
詳細ページを表示する際に何のデータを表示するかを指定する必要があるため。
from django.urls import path
from .views import TodoList, TodoDetail
urlpatterns = [
path('list/', TodoList.as_view()),
path('detail/<int:pk>', TodoDetail.as_view()),
]
class TodoDetail(DetailView):
template_name = 'detail.html'
model = TodoModel
templatesディレクトリ配下にdetail.htmlを作成
detailページは詳細画面なので多数のデータでなく、一つのデータ
を対象としているので、object_listではなく、objectを利用する。
{{ object.title }}
{{ object.memo }}
bootstrapで見た目をきれいにする
ドキュメントのスターターキットをコピーしてtemplateに貼り付けて、
bodyタグに中身を書く。
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<title>私は仕事が大好きです。</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; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" crossorigin="anonymous"></script>
-->
</body>
</html>
base.htmlを使用する。
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<title>私は仕事が大好きです。</title>
</head>
<body>
{% block header %}
{% endblock header %}
{% block content %}
{% endblock content %}
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" integrity="sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" integrity="sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" crossorigin="anonymous"></script>
-->
</body>
</html>
{% extends 'base.html' %}
{% 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 %}
一覧画面の見た目を整える
{% extends 'base.html' %}
{% block header %}
<div class="container">
<div class="bg-light p-3 p-sm-5 my-4 rounded">
<h1 class="display-4">Todolist</h1>
<p class="lead">Todolistを作って毎日を効率的に過ごしましょう。</p>
</div>
{% endblock %}
{% block content %}
<div class='container'>
{% for item in object_list %}
<div class="alert alert-secondary" role="alert">
<p>{{ item.title }}</p>
<a class="btn btn-info" href="#" role="button">編集</a>
<a class="btn btn-info" href="#" role="button">削除</a>
<a class="btn btn-info" href="#" role="button">詳細</a>
</div>
{% endfor %}
</div>
{% endblock %}
alert-のあとに変数が入るように変更。
<div class="alert alert-{{ item.priority }}" role="alert">
models.pyに以下を追加する。
PRIORITYはタプル型。左側は上記の変数に入る値。右側は画面で選択する際に表示される値。
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()
models.pyを変更したため、makemigrateを行う。
以下のように入力を求められる。
これは、「すでにあるデータのduedateの中身をどうするか?
デフォルトでnullを入力できません。」という内容。
1→何かしらの数字をセットする。
2→出直す。
manage.py@todoproject > makemigrations
You are trying to add a non-nullable field 'duedate' to todomodel without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
1を選ぶ。
どんな数字を入れますかと聞かれる。
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
timezone.nowを入力
priorityについても同じように聞かれる。
1を入力
'danger'を入力
You are trying to add a non-nullable field 'priority' to todomodel without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 'danger'
migrateを実行
manage.py@todoproject > migrate