You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在PyCharm中使用Flask、SQL、CSS、JavaScript、HTML创建含Google Keep风格复选框并支持价格存储的动态待办清单应用

Hey there! Let's walk through building your Google Keep-style todo app with Flask—complete with those satisfying toggleable checkboxes and database storage for tasks and their prices. I'll break this down into easy, actionable steps.

1. Project Setup & Dependencies

First, let's get the core tools installed. You'll need Flask for the web framework, and Flask-SQLAlchemy to simplify database interactions. Run this command in your terminal:

pip install flask flask-sqlalchemy
2. Database Model Setup

Create a main app file (let's call it app.py) and set up your Flask app with a database. We'll use SQLite for quick testing (you can swap it for PostgreSQL/MySQL later if needed).

Here's the code to define your todo model, which will store task content, price, and completion status:

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

app = Flask(__name__)
# Configure SQLite database (file will be created in your project folder)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # Disable unnecessary warnings
db = SQLAlchemy(app)

class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)  # Todo text
    price = db.Column(db.Float, nullable=False)  # Associated price
    is_completed = db.Column(db.Boolean, default=False)  # Checkbox state

    def __repr__(self):
        return f'<Todo {self.id}>'

# Initialize the database (run this once in a Python shell)
# from app import db; db.create_all()

if __name__ == '__main__':
    app.run(debug=True)

To create the database file, open a Python shell in your project folder, run from app import db; db.create_all(), then exit the shell.

3. Build the Google Keep-Style UI with Checkboxes

Google Keep's checkboxes toggle state without page reloads, so we'll use JavaScript + AJAX for that smooth experience. Create a templates folder, then add an index.html file with this code:

<!DOCTYPE html>
<html>
<head>
    <title>Keep-Style Todo List</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 2rem auto;
            padding: 0 1rem;
            background-color: #f5f5f5;
        }
        .todo-card {
            background: white;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            padding: 1rem;
            margin: 1rem 0;
            display: flex;
            align-items: center;
            gap: 1rem;
        }
        .todo-checkbox {
            width: 20px;
            height: 20px;
            cursor: pointer;
            accent-color: #4285f4;
        }
        .todo-content {
            flex: 1;
            font-size: 1rem;
            text-decoration: {{ 'line-through' if todo.is_completed else 'none' }};
            opacity: {{ 0.6 if todo.is_completed else 1 }};
            transition: all 0.2s ease;
        }
        .todo-price {
            color: #666;
            font-size: 0.9rem;
        }
        .add-form {
            margin: 2rem 0;
            display: flex;
            gap: 0.5rem;
        }
        .add-form input {
            padding: 0.75rem;
            border: 1px solid #ddd;
            border-radius: 4px;
            flex: 1;
            font-size: 1rem;
        }
        .add-form button {
            padding: 0.75rem 1.5rem;
            background-color: #4285f4;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 1rem;
        }
    </style>
</head>
<body>
    <h1>My Todo List</h1>
    <!-- Form to add new todos -->
    <form class="add-form" method="POST" action="{{ url_for('add_todo') }}">
        <input type="text" name="content" placeholder="Enter task..." required>
        <input type="number" step="0.01" name="price" placeholder="Enter price..." required>
        <button type="submit">Add Todo</button>
    </form>
    <!-- Render all todos -->
    {% for todo in todos %}
    <div class="todo-card">
        <input 
            type="checkbox" 
            class="todo-checkbox" 
            data-id="{{ todo.id }}" 
            {{ 'checked' if todo.is_completed else '' }}
        >
        <div class="todo-content">{{ todo.content }}</div>
        <div class="todo-price">${{ "%.2f"|format(todo.price) }}</div>
    </div>
    {% endfor %}

    <script>
        // Toggle todo completion status via AJAX
        document.querySelectorAll('.todo-checkbox').forEach(checkbox => {
            checkbox.addEventListener('change', function() {
                const todoId = this.getAttribute('data-id');
                const isCompleted = this.checked;

                fetch(`/toggle/${todoId}`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({is_completed: isCompleted}),
                })
                .then(response => response.json())
                .then(data => {
                    // Update text style without reloading
                    const contentElement = this.nextElementSibling;
                    if (isCompleted) {
                        contentElement.style.textDecoration = 'line-through';
                        contentElement.style.opacity = '0.6';
                    } else {
                        contentElement.style.textDecoration = 'none';
                        contentElement.style.opacity = '1';
                    }
                });
            });
        });
    </script>
</body>
</html>
4. Add Flask Routes for Core Features

Now add these routes to your app.py file to handle displaying todos, adding new ones, and toggling completion status:

@app.route('/')
def index():
    # Get all todos from the database
    todos = Todo.query.all()
    return render_template('index.html', todos=todos)

@app.route('/add', methods=['POST'])
def add_todo():
    # Get form data
    content = request.form['content']
    price = float(request.form['price'])
    # Create new todo entry
    new_todo = Todo(content=content, price=price)
    try:
        db.session.add(new_todo)
        db.session.commit()
        return redirect(url_for('index'))
    except:
        return 'There was an issue adding your task'

@app.route('/toggle/<int:id>', methods=['POST'])
def toggle_todo(id):
    # Find the todo by ID
    todo = Todo.query.get_or_404(id)
    # Update completion status from AJAX request
    data = request.get_json()
    todo.is_completed = data['is_completed']
    try:
        db.session.commit()
        return {'success': True}
    except:
        return {'success': False}, 500
5. Run the App

Start your Flask app by running:

python app.py

Visit http://localhost:5000 in your browser—you’ll see a clean, Keep-style todo list where you can add tasks with prices, and toggle checkboxes without page reloads!

Quick Optimizations to Enhance the App

  • Add a delete button for todos (similar to the toggle logic with AJAX)
  • Customize the checkbox style to match Google Keep’s circular design
  • Add edit functionality for task content and prices
  • For production, switch to a robust database like PostgreSQL and disable debug mode

内容的提问来源于stack exchange,提问作者Lucy Sunday

火山引擎 最新活动