Pythonを使った簡単なTODOアプリの作成

# はじめに
この記事では、Pythonを使って簡単なTODOアプリを作成する方法を紹介します。TODOアプリは、基本的なCRUD（Create, Read, Update, Delete）操作を通じてPythonの基本を学ぶのに最適です。

# 前提条件
* Python 3.7以上
* 仮想環境 (venv)
* Flaskフレームワーク
* SQLiteデータベース


# プロジェクトのセットアップ
1. プロジェクトディレクトリを作成します。

```bash
mkdir todo_app
cd todo_app
```
<br>
2. 仮想環境を作成し、アクティベートします。

```bash
python -m venv venv
source venv/bin/activate  # Windowsの場合は `venv\Scripts\activate`
```
<br>
3. Flaskをインストールします。

```bash
pip install Flask
```

# ディレクトリ構造

```
todo_app/
|-- app.py
|-- templates/
|   |-- index.html
|-- static/
|   |-- style.css
```

# 1. アプリケーションの作成
app.py

```python
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)
    completed = db.Column(db.Boolean, default=False)

    def __repr__(self):
        return f'<Task {self.id} - {self.content}>'

@app.route('/')
def index():
    tasks = Todo.query.all()
    return render_template('index.html', tasks=tasks)

@app.route('/add', methods=['POST'])
def add():
    task_content = request.form['content']
    new_task = Todo(content=task_content)

    try:
        db.session.add(new_task)
        db.session.commit()
        return redirect('/')
    except:
        return 'There was an issue adding your task'

@app.route('/delete/<int:id>')
def delete(id):
    task_to_delete = Todo.query.get_or_404(id)

    try:
        db.session.delete(task_to_delete)
        db.session.commit()
        return redirect('/')
    except:
        return 'There was a problem deleting that task'

@app.route('/update/<int:id>', methods=['GET', 'POST'])
def update(id):
    task = Todo.query.get_or_404(id)

    if request.method == 'POST':
        task.content = request.form['content']
        task.completed = 'completed' in request.form

        try:
            db.session.commit()
            return redirect('/')
        except:
            return 'There was an issue updating your task'
    else:
        return render_template('update.html', task=task)

if __name__ == "__main__":
    db.create_all()
    app.run(debug=True)
```

# 2. テンプレートの作成
templates/index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TODOアプリ</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <div class="container">
        <h1>TODOリスト</h1>
        <form action="/add" method="POST">
            <input type="text" name="content" placeholder="新しいタスクを追加">
            <button type="submit">追加</button>
        </form>
        <ul>
            {% for task in tasks %}
            <li>
                <span class="{{ 'completed' if task.completed else '' }}">{{ task.content }}</span>
                <a href="/update/{{ task.id }}">更新</a>
                <a href="/delete/{{ task.id }}">削除</a>
            </li>
            {% endfor %}
        </ul>
    </div>
</body>
</html>
```

templates/update.html
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TODOアプリ - 更新</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <div class="container">
        <h1>タスクを更新</h1>
        <form action="/update/{{ task.id }}" method="POST">
            <input type="text" name="content" value="{{ task.content }}">
            <label>
                <input type="checkbox" name="completed" {% if task.completed %}checked{% endif %}>
                完了
            </label>
            <button type="submit">更新</button>
        </form>
        <a href="/">戻る</a>
    </div>
</body>
</html>
```

# 3. スタイルシートの作成
static/style.css
```css
body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    margin: 0;
    padding: 0;
}

.container {
    width: 80%;
    margin: auto;
    overflow: hidden;
    padding: 20px;
}

h1 {
    text-align: center;
}

form {
    display: flex;
    justify-content: center;
    margin-bottom: 20px;
}

form input[type="text"] {
    padding: 10px;
    font-size: 16px;
    width: 70%;
    margin-right: 10px;
    border: 1px solid #ddd;
}

form button {
    padding: 10px;
    font-size: 16px;
    background-color: #007bff;
    color: white;
    border: none;
    cursor: pointer;
}

form button:hover {
    background-color: #0056b3;
}

ul {
    list-style: none;
    padding: 0;
}

ul li {
    background: white;
    margin-bottom: 10px;
    padding: 10px;
    display: flex;
    justify-content: space-between;
    border: 1px solid #ddd;
}

ul li span.completed {
    text-decoration: line-through;
}

ul li a {
    color: #007bff;
    text-decoration: none;
}

ul li a:hover {
    text-decoration: underline;
}
```

# 4. アプリケーションの実行
1. 仮想環境がアクティベートされていることを確認します。
2. アプリケーションを起動します。

    ```
    python app.py
    ```
3. ブラウザで http://localhost:5000 にアクセスします。


これで、簡単なTODOアプリが動作するはずです。新しいタスクの追加、タスクの更新、タスクの削除が行えます。

# さいごに
この記事では、PythonとFlaskを使って簡単なTODOアプリを作成する方法を紹介しました。この基本的なCRUDアプリケーションを通じて、Flaskの基本的な使い方や、データベース操作の方法を学ぶことができます。Flaskはシンプルで強力なフレームワークであり、より複雑なアプリケーションの開発にも適しています。