如何在PyCharm中使用Flask、SQL、CSS、JavaScript、HTML开发带Google Keep式勾选框的动态待办清单并实现价格存储功能?
Hey Lucy, great choice building a Google Keep-style todo app—let's walk through exactly how to pull this off in PyCharm using Flask, SQL, and frontend tools. I'll break it down into actionable steps with code snippets you can copy-paste and tweak.
First, get your environment ready:
- Create a new PyCharm project, select "Flask" as the template (this auto-sets up a virtual environment)
- If you start from scratch, manually create a virtual env and install dependencies via PyCharm's terminal:
pip install flask flask-sqlalchemy
Let's build the core backend with a SQLite database (easy for testing) to store todos, their completion status, and prices.
Step 2.1: Initialize Flask & Database
Create app.py in your project root:
from flask import Flask, render_template, request, redirect, url_for from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # Configure SQLite database app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) # Todo Model: Stores content, completion status, and price class Todo(db.Model): id = db.Column(db.Integer, primary_key=True) content = db.Column(db.String(200), nullable=False) done = db.Column(db.Boolean, default=False) # Tracks if todo is checked price = db.Column(db.Float, nullable=False) # Stores the associated price # Create database tables (run this once in Flask shell) with app.app_context(): db.create_all()
Step 2.2: Add Core Routes
Add these routes to app.py for CRUD operations:
# Home page: Show all todos @app.route('/') def index(): todos = Todo.query.all() return render_template('index.html', todos=todos) # Add new todo with price @app.route('/add', methods=['POST']) def add_todo(): content = request.form.get('content') price = request.form.get('price') if content and price: new_todo = Todo(content=content, price=float(price)) db.session.add(new_todo) db.session.commit() return redirect(url_for('index')) # Toggle todo completion status @app.route('/toggle/<int:todo_id>') def toggle_done(todo_id): todo = Todo.query.get_or_404(todo_id) todo.done = not todo.done db.session.commit() return redirect(url_for('index')) # Delete a todo @app.route('/delete/<int:todo_id>') def delete_todo(todo_id): todo = Todo.query.get_or_404(todo_id) db.session.delete(todo) db.session.commit() return redirect(url_for('index')) if __name__ == '__main__': app.run(debug=True)
Create two folders: templates (for HTML) and static (for CSS/JS) in your project root.
Step 3.1: HTML Template (templates/index.html)
This builds the card-based layout and connects to backend data:
<!DOCTYPE html> <html> <head> <title>Keep-Style Todo List</title> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> </head> <body> <div class="container"> <h1>My Todo List</h1> <!-- Add Todo Form --> <form action="/add" method="POST" class="add-form"> <input type="text" name="content" placeholder="Enter todo..." required> <input type="number" step="0.01" name="price" placeholder="Enter price ($)" required> <button type="submit">Add Todo</button> </form> <!-- Todo Cards --> <div class="todo-grid"> {% for todo in todos %} <div class="todo-card {% if todo.done %}completed{% endif %}"> <a href="/toggle/{{ todo.id }}" class="check-circle"> {% if todo.done %}✓{% endif %} </a> <div class="todo-content"> <p>{{ todo.content }}</p> <span class="price">$ {{ "%.2f"|format(todo.price) }}</span> </div> <a href="/delete/{{ todo.id }}" class="delete-btn">×</a> </div> {% endfor %} </div> </div> <script src="{{ url_for('static', filename='script.js') }}"></script> </body> </html>
Step 3.2: CSS for Google Keep Style (static/style.css)
This mimics Keep's soft cards and custom checkboxes:
body { font-family: 'Roboto', sans-serif; background-color: #f8f9fa; margin: 0; padding: 2rem; } .container { max-width: 900px; margin: 0 auto; } .add-form { background: white; padding: 1.2rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 2rem; display: flex; gap: 0.8rem; } .add-form input { flex: 1; padding: 0.6rem; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 1rem; } .add-form button { background: #20c997; color: white; border: none; padding: 0.6rem 1.2rem; border-radius: 4px; cursor: pointer; transition: background 0.2s; } .add-form button:hover { background: #17a689; } .todo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1.5rem; } .todo-card { background: white; padding: 1.2rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); display: flex; align-items: flex-start; gap: 1rem; transition: all 0.3s ease; } .todo-card.completed { opacity: 0.7; background-color: #f0fff4; } .check-circle { width: 22px; height: 22px; border: 2px solid #4dabf7; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; color: transparent; font-weight: bold; transition: all 0.2s; } .todo-card.completed .check-circle { background-color: #20c997; border-color: #20c997; color: white; } .todo-content { flex: 1; } .todo-content p { margin: 0 0 0.5rem 0; font-size: 1rem; } .price { font-size: 0.9rem; color: #6c757d; } .delete-btn { color: #dc3545; text-decoration: none; font-size: 1.2rem; line-height: 1; opacity: 0.6; transition: opacity 0.2s; } .delete-btn:hover { opacity: 1; }
Step 3.3: JS for Smooth Interactions (static/script.js)
Add optional no-refresh toggle for checkboxes:
document.querySelectorAll('.check-circle').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const card = this.closest('.todo-card'); card.classList.toggle('completed'); // Update backend without page reload fetch(this.href) .then(response => { if (response.ok) return; card.classList.toggle('completed'); // Revert if error }); }); });
- Set up a Flask run configuration: Go to
Run > Edit Configurations, add a Flask configuration, setFLASK_APPtoapp.py, and enable debug mode. - Click "Run"—your app will start at
http://localhost:5000 - Test adding todos with prices, checking off items, and deleting entries. You can view the SQLite database in PyCharm's "Database" tool to verify prices are stored correctly.
- Add color labels like Google Keep using CSS classes and a dropdown in the add form
- Implement todo editing with a modal
- Use Flask-WTF for better form validation
- Switch to PostgreSQL/MySQL for production use
内容的提问来源于stack exchange,提问作者Lucy Sunday




