Closed10
Flaskでtodoアプリ作成(練習)
以下のサイトを参考にして自分流に作成中
ディレクトリ構造
|-- app.py
|-- createdb.py #DBを作成するだけのソース
|-- static
| |-- css
| | `-- bootstrap.css
| |-- jquery-3.6.1.min.js
| `-- js
| `-- bootstrap.bundle.min.js
|-- templates
| |-- base.html
| |-- create.html
| |-- detail.html
| |-- index.html
| `-- update.html
`-- todo.db #createdb.pyで作成したDB
コメントないけどapp.py
app.py
from flask import Flask, render_template, url_for, request, redirect, g
from datetime import datetime
import sqlite3
app = Flask(__name__)
def get_db():
if 'db' not in g:
dbname = 'todo.db'
g.db = sqlite3.connect(dbname)
return g.db
@app.route('/', methods=['GET', 'POST'])
def index():
conn = get_db()
cur = conn.cursor()
if request.method == 'GET':
res = cur.execute('SELECT id, title, detail, date(datetime(due)) as due FROM todo').fetchall()
conn.close()
return render_template('index.html', posts=res)
else:
res = cur.execute('SELECT id FROM todo ORDER BY id DESC').fetchone()
if res is None:
id = 1
else:
id = res[0] + 1
title = request.form.get('title')
detail = request.form.get('detail')
due = request.form.get('due')
due = datetime.strptime(due, '%Y-%m-%d')
cur.execute('INSERT INTO todo VALUES(:id, :title, :detail, :due)',
{'id': id, 'title': title, 'detail': detail, 'due': due})
conn.commit()
conn.close()
return redirect('/')
@app.route('/create')
def create():
return render_template('create.html')
@app.route('/detail/<int:id>')
def read(id):
conn = get_db()
cur = conn.cursor()
res = cur.execute('SELECT title, detail, date(datetime(due)) as due FROM todo WHERE id =:id', {'id': id}).fetchone()
conn.close()
return render_template('detail.html', post=res)
if __name__ == "__main__":
app.run(debug=True, host='xxx.xxx.xxx.xxx', port=1234)
改変 index.html
index.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<a class="btn btn-info btn-lg m-5" href="/create" role="button">新しいタスク</a>
{% for post in posts %}
<div class="card w-50 mb-3" style="margin: auto;">
<div class="card-body">
<h2>タイトル : {{ post[1] }}</h2>
<p>期限 : {{ post[3] }}</p>
<a href="/detail/{{ post[0] }}" role="button">詳細</a>
<a href="/update/{{ post[0] }}" role="button">更新</a>
<a href="/delete/{{ post[0] }}" role="button">削除</a>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
```
改変 detail.html
detail.html
{% extends 'base.html' %}
{%block body %}
<h2 class="m-5" style="text-align: center;">詳細</h2>
<div class="card w-50 mb-3" style="margin: auto;">
<div class="card-body">
<h2 class="card-title">{{ post[1] }} <span class="ml-3"
style="font-size: 0.5em;">期限:{{ post[3] }}</span></h2>
<p>{{ post[2] }}</p>
<div class="pt-2">
<a class="btn btn-outline-success" href="/" role="button">戻る</a>
<a class="btn btn-success" href="/update/{{ post[0] }}" role="button">更新</a>
</div>
</div>
</div>
{% endblock %}
todoテーブル
CREATE TABLE todo(id INTEGER PRIMARY KEY, title VARCHAR(30) NOT NULL, detail VARCHAR(100), due TIMESTAMP not null);
id | title | detail | due |
---|---|---|---|
1 | aaa | bbbbb | 2022-10-18 00:00:00 |
2 | テスト | でーす | 2022-10-19 00:00:00 |
テーブルレイアウトが良くないかなぁ
app.pyでこれをするならIDはAUTOINCLIMENTでもよかったかも?
それかデータの論理削除項目を追加するか
res = cur.execute('SELECT id FROM todo ORDER BY id DESC').fetchone()
if res is None:
id = 1
else:
id = res[0] + 1
update.html
{% extends 'base.html' %}
{% block body %}
<h2 class="m-5">編集</h2>
<form class="m-5" action="/update/{{ post[0] }}" method="POST">
<div class="form-group pb-3">
<label for="title">Title : </label>
<input type="text" class="form-control" name="title" aria-describedby="title-help" value={{ post[1] }}>
</div>
<div class="form-group pb-3">
<label for="detail">Detail : </label>
<input type="text" class="form-control" name="detail" value={{ post[2] }}>
</div>
<div class="form-group pb-3">
<label for="due">Due : </label>
<input type="date" name="due" value={{ post[3] }} required>
</div>
<a class="btn btn-outline-primary" href="/" role="button">Return</a>
<button type="submit" class="btn btn-primary">Change</button>
</form>
{% endblock %}
jQueryはなくても良かった
base.html
<!DOCUTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="{{url_for('static', filename='css/bootstrap.css')}}")>
<title>Todoアプリ</title>
{% block head %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-light bg-light p-3">
<a class="navbar-brand p1-3" href="/" style="font-size: 2rem;">Todoアプリ</a>
</nav>
{% block body %}{% endblock %}
<!-- <script src="{{url_for('static', filename='jquery-3.6.1.min.js')}}")></script> -->
<script src="{{url_for('static', filename='js/bootstrap.bundle.min.js')}}"></script>
</body>
</html>
参考サイトには期限切れのタスクは注意書きが表示されるようになっていたけどjinjaで日付を文字列から日付型に変換する必要があった。
やり方がわからないから削る。
このスクラップは2022/10/22にクローズされました