1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DjangoでTodoアプリを作成その1

Last updated at Posted at 2021-03-22

pycharmでプロジェクトを作成する。
スクリーンショット 2021-03-22 12.18.43.png

satrt appコマンドでtodoアプリを作成する。
スクリーンショット 2021-03-22 12.19.21.png

todoアプリを追加する。

setteings.py
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につなげる。

todoproject/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は長めの文字のための型

todo/models.py
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にデータをセットできるようにする。

todo/admin.py
from django.contrib import admin
from .models import TodoModel

# Register your models here.

admin.site.register(TodoModel)
管理画面のデータ一覧画面の表示を変更

タイトルが表示されるようにする。

todo/admin.py
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の作成
todo/urls.py
from django.urls import path
from .views import TodoList

urlpatterns = [
    path('list/', TodoList.as_view()),
]

modelでmodels.pyにあるどのmodelを使用するかを指示する。

todo/views.py
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のオブジェクトが入っている。

list.html
{% for post in object_list %}
    {{ post.title }}
    {{ post.memo }}
{% endfor %}

DatailView

データの中身を表示することに適したテンプレート
int:pkとはinteger型のプライマリーキーのこと。
詳細ページを表示する際に何のデータを表示するかを指定する必要があるため。

todo/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()),
]
todo/views.py
class TodoDetail(DetailView):
    template_name = 'detail.html'
    model = TodoModel

templatesディレクトリ配下にdetail.htmlを作成

detailページは詳細画面なので多数のデータでなく、一つのデータ
を対象としているので、object_listではなく、objectを利用する。

detail.html
{{ object.title }}
{{ object.memo }}

bootstrapで見た目をきれいにする

bootstrap

ドキュメントのスターターキットをコピーしてtemplateに貼り付けて、
bodyタグに中身を書く。

templates/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">

    <!-- 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を使用する。

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>
list.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 %}

一覧画面の見た目を整える

list.html
{%  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-のあとに変数が入るように変更。

list.html
        <div class="alert alert-{{ item.priority }}" role="alert">

models.pyに以下を追加する。
PRIORITYはタプル型。左側は上記の変数に入る値。右側は画面で選択する際に表示される値。

models.py

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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?