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

如何在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.


1. Project Setup in PyCharm

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
    
2. Flask Backend & SQL Database Configuration

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)
3. Google Keep-Style Frontend (HTML/CSS/JS)

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
            });
    });
});
4. Run & Test in PyCharm
  • Set up a Flask run configuration: Go to Run > Edit Configurations, add a Flask configuration, set FLASK_APP to app.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.
5. Optional Enhancements
  • 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

火山引擎 最新活动