Project Overview

Developed a complete Todo List full-stack application using front-end and back-end separation architecture. The frontend uses native JavaScript + jQuery technology stack, the backend is based on Python Flask framework, with SQLite database, implementing complete task management functionality.

Technical Architecture

Frontend Technology Stack

  • Native JavaScript: Core business logic
  • jQuery 3.x: DOM manipulation and AJAX requests
  • HTML5: Semantic structure
  • CSS3: Responsive layout and animation effects

Backend Technology Stack

  • Python Flask: Lightweight web framework
  • SQLite: Embedded database
  • RESTful API: Standardized interface design
  • JSON: Data exchange format

Feature Design

Core Features

  1. Task Creation: Add new todo items
  2. Task Viewing: Display all task lists
  3. Task Editing: Modify task content and status
  4. Task Deletion: Remove completed or unwanted tasks
  5. Status Toggle: Mark tasks as completed/incomplete
  6. Data Persistence: Save task information to database

Interface Features

  • Clean Design: Clear task display interface
  • Real-time Updates: Operations immediately reflected in the interface
  • Responsive Layout: Adapts to different screen sizes
  • Friendly Interaction: Intuitive user operation experience

Frontend Implementation

JavaScript Core Logic

// Task management class
class TodoManager {
    constructor() {
        this.tasks = [];
        this.init();
    }

    // Initialize application
    init() {
        this.bindEvents();
        this.loadTasks();
    }

    // Bind event handlers
    bindEvents() {
        $('#add-task-btn').on('click', () => this.addTask());
        $('#task-input').on('keypress', (e) => {
            if (e.which === 13) this.addTask();
        });
        $(document).on('click', '.delete-btn', (e) => {
            this.deleteTask($(e.target).data('id'));
        });
        $(document).on('change', '.task-checkbox', (e) => {
            this.toggleTask($(e.target).data('id'));
        });
    }

    // Add task
    async addTask() {
        const taskText = $('#task-input').val().trim();
        if (!taskText) return;

        try {
            const response = await $.post('/api/tasks', {
                text: taskText,
                completed: false
            });
            this.renderTask(response);
            $('#task-input').val('');
        } catch (error) {
            console.error('Failed to add task:', error);
        }
    }

    // Delete task
    async deleteTask(taskId) {
        try {
            await $.ajax({
                url: `/api/tasks/${taskId}`,
                method: 'DELETE'
            });
            $(`[data-id="${taskId}"]`).closest('.task-item').remove();
        } catch (error) {
            console.error('Failed to delete task:', error);
        }
    }

    // Toggle task status
    async toggleTask(taskId) {
        try {
            const response = await $.ajax({
                url: `/api/tasks/${taskId}`,
                method: 'PUT',
                data: { completed: !this.getTaskById(taskId).completed }
            });
            this.updateTaskDisplay(response);
        } catch (error) {
            console.error('Failed to update task:', error);
        }
    }

    // Render task list
    renderTasks(tasks) {
        const $taskList = $('#task-list');
        $taskList.empty();
        
        tasks.forEach(task => this.renderTask(task));
    }

    // Render single task
    renderTask(task) {
        const taskHtml = `
            <div class="task-item ${task.completed ? 'completed' : ''}">
                <input type="checkbox" class="task-checkbox" 
                       data-id="${task.id}" ${task.completed ? 'checked' : ''}>
                <span class="task-text">${task.text}</span>
                <button class="delete-btn" data-id="${task.id}">Delete</button>
            </div>
        `;
        $('#task-list').append(taskHtml);
    }
}

// Initialize application
$(document).ready(() => {
    new TodoManager();
});

CSS Style Design

/* Main container styles */
.todo-container {
    max-width: 600px;
    margin: 50px auto;
    padding: 20px;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

/* Input section */
.input-section {
    display: flex;
    margin-bottom: 30px;
    gap: 10px;
}

#task-input {
    flex: 1;
    padding: 12px;
    border: 2px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
}

#add-task-btn {
    padding: 12px 20px;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.3s;
}

#add-task-btn:hover {
    background: #0056b3;
}

/* Task list */
.task-item {
    display: flex;
    align-items: center;
    padding: 15px;
    border-bottom: 1px solid #eee;
    transition: background 0.3s;
}

.task-item:hover {
    background: #f8f9fa;
}

.task-item.completed {
    opacity: 0.6;
}

.task-item.completed .task-text {
    text-decoration: line-through;
}

.task-checkbox {
    margin-right: 15px;
}

.task-text {
    flex: 1;
    font-size: 16px;
}

.delete-btn {
    background: #dc3545;
    color: white;
    border: none;
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
}

.delete-btn:hover {
    background: #c82333;
}

Backend Implementation

Flask API Service

from flask import Flask, request, jsonify, render_template
import sqlite3
import json
from datetime import datetime

app = Flask(__name__)

# Database initialization
def init_db():
    conn = sqlite3.connect('todo.db')
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            text TEXT NOT NULL,
            completed BOOLEAN DEFAULT FALSE,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    conn.commit()
    conn.close()

# Get all tasks
@app.route('/api/tasks', methods=['GET'])
def get_tasks():
    conn = sqlite3.connect('todo.db')
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM tasks ORDER BY created_at DESC')
    tasks = []
    for row in cursor.fetchall():
        tasks.append({
            'id': row[0],
            'text': row[1],
            'completed': bool(row[2]),
            'created_at': row[3],
            'updated_at': row[4]
        })
    conn.close()
    return jsonify(tasks)

# Create new task
@app.route('/api/tasks', methods=['POST'])
def create_task():
    data = request.get_json() or request.form
    text = data.get('text', '').strip()
    
    if not text:
        return jsonify({'error': 'Task content cannot be empty'}), 400
    
    conn = sqlite3.connect('todo.db')
    cursor = conn.cursor()
    cursor.execute(
        'INSERT INTO tasks (text, completed) VALUES (?, ?)',
        (text, data.get('completed', False))
    )
    task_id = cursor.lastrowid
    conn.commit()
    conn.close()
    
    return jsonify({
        'id': task_id,
        'text': text,
        'completed': data.get('completed', False),
        'created_at': datetime.now().isoformat()
    }), 201

# Update task
@app.route('/api/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
    data = request.get_json() or request.form
    
    conn = sqlite3.connect('todo.db')
    cursor = conn.cursor()
    
    # Check if task exists
    cursor.execute('SELECT * FROM tasks WHERE id = ?', (task_id,))
    task = cursor.fetchone()
    if not task:
        conn.close()
        return jsonify({'error': 'Task not found'}), 404
    
    # Update task
    text = data.get('text', task[1])
    completed = data.get('completed', task[2])
    
    cursor.execute(
        'UPDATE tasks SET text = ?, completed = ?, updated_at = ? WHERE id = ?',
        (text, completed, datetime.now().isoformat(), task_id)
    )
    conn.commit()
    conn.close()
    
    return jsonify({
        'id': task_id,
        'text': text,
        'completed': completed,
        'updated_at': datetime.now().isoformat()
    })

# Delete task
@app.route('/api/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
    conn = sqlite3.connect('todo.db')
    cursor = conn.cursor()
    cursor.execute('DELETE FROM tasks WHERE id = ?', (task_id,))
    
    if cursor.rowcount == 0:
        conn.close()
        return jsonify({'error': 'Task not found'}), 404
    
    conn.commit()
    conn.close()
    return jsonify({'message': 'Task deleted successfully'})

# Home route
@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    init_db()
    app.run(debug=True, host='0.0.0.0', port=5000)

Project Features

1. Front-End and Back-End Separation

  • Clear separation of responsibilities
  • RESTful API design
  • Frontend focuses on user interaction, backend focuses on data processing

2. Reasonable Technology Selection

  • Native JavaScript ensures performance
  • jQuery simplifies DOM operations
  • Flask is lightweight and easy to develop
  • SQLite is a zero-configuration database

3. Well-Organized Code

  • Modular JavaScript class design
  • Clear CSS style structure
  • Standard Flask route organization

4. Excellent User Experience

  • Real-time response to user operations
  • Intuitive visual feedback
  • Clean and beautiful interface design

Deployment and Running

Local Development Environment

# Backend startup
pip install flask
python app.py

# Frontend access
http://localhost:5000

Directory Structure

todo-app/
├── app.py                 # Flask backend service
├── todo.db               # SQLite database
├── templates/
│   └── index.html        # Main page template
├── static/
│   ├── js/
│   │   └── app.js        # Frontend JavaScript
│   └── css/
│       └── style.css     # Style files
└── requirements.txt      # Python dependencies

Technical Insights and Reflections

Architecture Design

  • Front-end and back-end separation improved development efficiency and maintainability
  • RESTful API design ensured interface standardization
  • Lightweight technology stack reduced project complexity

Development Experience

  • Native JavaScript provided better performance control
  • jQuery greatly simplified DOM operations and AJAX requests
  • Flask’s simplicity accelerated development progress

Code Quality

  • Modular design improved code reusability
  • Exception handling ensured application stability
  • Data validation ensured data integrity

Future Optimization Directions

  1. Feature Expansion: Task categories, priorities, deadlines
  2. Performance Optimization: Paginated loading, caching mechanisms
  3. User System: Login registration, multi-user support
  4. Interface Enhancement: Drag-and-drop sorting, batch operations
  5. Mobile Adaptation: PWA support, offline functionality

Summary

This Todo List full-stack application successfully implemented a front-end and back-end separated architecture design. Through reasonable technology selection and clear code organization, it built a feature-complete task management application with good user experience.

The project demonstrates how to use classic Web technology stack to build modern applications, laying a solid foundation for further feature expansion and technology upgrades.

Ge Yuxu • AI & Engineering

脱敏说明:本文所有出现的表名、字段名、接口地址、变量名、IP地址及示例数据等均非真实,仅用于阐述技术思路与实现步骤,示例代码亦非公司真实代码。示例方案亦非公司真实完整方案,仅为本人记忆总结,用于技术学习探讨。
    • 文中所示任何标识符并不对应实际生产环境中的名称或编号。
    • 示例 SQL、脚本、代码及数据等均为演示用途,不含真实业务数据,也不具备直接运行或复现的完整上下文。
    • 读者若需在实际项目中参考本文方案,请结合自身业务场景及数据安全规范,使用符合内部命名和权限控制的配置。

Data Desensitization Notice: All table names, field names, API endpoints, variable names, IP addresses, and sample data appearing in this article are fictitious and intended solely to illustrate technical concepts and implementation steps. The sample code is not actual company code. The proposed solutions are not complete or actual company solutions but are summarized from the author's memory for technical learning and discussion.
    • Any identifiers shown in the text do not correspond to names or numbers in any actual production environment.
    • Sample SQL, scripts, code, and data are for demonstration purposes only, do not contain real business data, and lack the full context required for direct execution or reproduction.
    • Readers who wish to reference the solutions in this article for actual projects should adapt them to their own business scenarios and data security standards, using configurations that comply with internal naming and access control policies.

版权声明:本文版权归原作者所有,未经作者事先书面许可,任何单位或个人不得以任何方式复制、转载、摘编或用于商业用途。
    • 若需非商业性引用或转载本文内容,请务必注明出处并保持内容完整。
    • 对因商业使用、篡改或不当引用本文内容所产生的法律纠纷,作者保留追究法律责任的权利。

Copyright Notice: The copyright of this article belongs to the original author. Without prior written permission from the author, no entity or individual may copy, reproduce, excerpt, or use it for commercial purposes in any way.
    • For non-commercial citation or reproduction of this content, attribution must be given, and the integrity of the content must be maintained.
    • The author reserves the right to pursue legal action against any legal disputes arising from the commercial use, alteration, or improper citation of this article's content.

Copyright © 1989–Present Ge Yuxu. All Rights Reserved.