当前位置: 首页 > news >正文

Python+Flutter前后端分离开发跨平台待办事项APP实战

以下是一个简单的示例,展示如何使用 Flutter 开发一个待办事项应用,并通过 FastAPI 和 SQLAlchemy 作为后端接口。为了简化代码,所有的 Flutter 前端代码将写在一个 main.dart 文件中。

1. 后端部分(FastAPI + SQLAlchemy)

首先,我们需要创建一个简单的 FastAPI 后端服务,用于处理待办事项的增删改查操作。

安装依赖

在你的 Python 环境中安装以下依赖:

pip install fastapi uvicorn sqlalchemy

创建 FastAPI 应用

创建一个文件 main.py,并写入以下代码:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库配置
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

# 待办事项模型
class TodoItem(Base):
    __tablename__ = "todo_items"
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    completed = Column(Boolean, default=False)

# 创建数据库表
Base.metadata.create_all(bind=engine)

# Pydantic 模型
class TodoItemCreate(BaseModel):
    title: str

class TodoItemUpdate(BaseModel):
    title: str = None
    completed: bool = None

# FastAPI 应用
app = FastAPI()

# 获取数据库会话
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# 获取所有待办事项
@app.get("/todos/")
def read_todos():
    db = SessionLocal()
    items = db.query(TodoItem).all()
    return [{"id": item.id, "title": item.title, "completed": item.completed} for item in items]

# 创建待办事项
@app.post("/todos/")
def create_todo(item: TodoItemCreate):
    db = SessionLocal()
    new_item = TodoItem(title=item.title, completed=False)
    db.add(new_item)
    db.commit()
    db.refresh(new_item)
    return {"id": new_item.id, "title": new_item.title, "completed": new_item.completed}

# 更新待办事项
@app.put("/todos/{todo_id}")
def update_todo(todo_id: int, item: TodoItemUpdate):
    db = SessionLocal()
    db_item = db.query(TodoItem).filter(TodoItem.id == todo_id).first()
    if not db_item:
        raise HTTPException(status_code=404, detail="Item not found")
    if item.title is not None:
        db_item.title = item.title
    if item.completed is not None:
        db_item.completed = item.completed
    db.commit()
    db.refresh(db_item)
    return {"id": db_item.id, "title": db_item.title, "completed": db_item.completed}

# 删除待办事项
@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):
    db = SessionLocal()
    db_item = db.query(TodoItem).filter(TodoItem.id == todo_id).first()
    if not db_item:
        raise HTTPException(status_code=404, detail="Item not found")
    db.delete(db_item)
    db.commit()
    return {"message": "Item deleted"}

启动 FastAPI 服务

运行以下命令启动服务:

uvicorn main:app --reload

服务默认运行在 http://127.0.0.1:8000,你可以通过访问 /docs 查看 API 文档。

2. Flutter 前端部分(main.dart)

接下来,我们编写 Flutter 应用来与后端交互。所有代码将写在一个 main.dart 文件中。

安装依赖

在 Flutter 项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.5
  provider: ^6.0.5

运行 flutter pub get 安装依赖。

编写 Flutter 代码

以下是完整的 main.dart 文件代码:

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Todo App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TodoListScreen(),
    );
  }
}

class TodoListScreen extends StatefulWidget {
  
  _TodoListScreenState createState() => _TodoListScreenState();
}

class _TodoListScreenState extends State<TodoListScreen> {
  List<dynamic> _todos = [];
  final TextEditingController _textEditingController = TextEditingController();

  
  void initState() {
    super.initState();
    _fetchTodos();
  }

  Future<void> _fetchTodos() async {
    try {
      final response = await http.get(Uri.parse('http://127.0.0.1:8000/todos/'));
      if (response.statusCode == 200) {
        setState(() {
          _todos = json.decode(response.body);
        });
      } else {
        throw Exception('Failed to load todos');
      }
    } catch (e) {
      print('Error fetching todos: $e');
    }
  }

  Future<void> _createTodo(String title) async {
    try {
      final response = await http.post(
        Uri.parse('http://127.0.0.1:8000/todos/'),
        headers: {'Content-Type': 'application/json'},
        body: json.encode({'title': title}),
      );
      if (response.statusCode == 200) {
        _fetchTodos();
      } else {
        throw Exception('Failed to create todo');
      }
    } catch (e) {
      print('Error creating todo: $e');
    }
  }

  Future<void> _updateTodo(int id, {String? title, bool? completed}) async {
    try {
      final response = await http.put(
        Uri.parse('http://127.0.0.1:8000/todos/$id'),
        headers: {'Content-Type': 'application/json'},
        body: json.encode({
          'title': title,
          'completed': completed,
        }),
      );
      if (response.statusCode == 200) {
        _fetchTodos();
      } else {
        throw Exception('Failed to update todo');
      }
    } catch (e) {
      print('Error updating todo: $e');
    }
  }

  Future<void> _deleteTodo(int id) async {
    try {
      final response = await http.delete(Uri.parse('http://127.0.0.1:8000/todos/$id'));
      if (response.statusCode == 200) {
        _fetchTodos();
      } else {
        throw Exception('Failed to delete todo');
      }
    } catch (e) {
      print('Error deleting todo: $e');
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Todo List'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (context, index) {
                final todo = _todos[index];
                return ListTile(
                  title: Text(todo['title']),
                  trailing: Checkbox(
                    value: todo['completed'],
                    onChanged: (bool? value) {
                      _updateTodo(todo['id'], completed: value);
                    },
                  ),
                  onLongPress: () {
                    _deleteTodo(todo['id']);
                  },
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _textEditingController,
                    decoration: InputDecoration(
                      hintText: 'Enter a new todo',
                    ),
                  ),
                ),
                IconButton(
                  icon: Icon(Icons.add),
                  onPressed: () {
                    final title = _textEditingController.text;
                    if (title.isNotEmpty) {
                      _createTodo(title);
                      _textEditingController.clear();
                    }
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

3. 运行和测试

启动 FastAPI 后端服务:

uvicorn main:app --reload

运行 Flutter 应用:
在 Flutter 项目目录下运行:

flutter run

测试功能:

  • 在 Flutter 应用中添加待办事项,查看是否成功保存到后端。
  • 勾选或取消勾选待办事项,查看是否更新状态。
  • 长按待办事项删除,查看是否从后端删除。

相关文章:

  • 微信小程序:完善购物车功能,购物车主页面展示,详细页面展示效果
  • R 语言科研绘图 --- 柱状图-汇总
  • CSS编程基础学习
  • 每日一题——顺时针旋转矩阵
  • 基于 GEE 计算并下载研究区年均叶面积指数 LAI 和光合有效辐射分量 FPAR
  • 量子计算在金融风险评估中的应用:革新与突破
  • dify本地部署
  • Python--函数高级(上)
  • tauri输入js脚本的方法和注意事项initialization_script
  • 什么是MySql的主从复制(主从同步)?
  • 开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B-Docker助力-模型部署 “光速” 指南
  • MySQL-数据库的基本操作
  • 我与Linux的爱恋:了解信号量+共享内存+消息队列的应用
  • zookeeper 客户端常用命令
  • Unity3D实现编辑器截屏Preview窗口,并生成图片PNG
  • 【MySQL学习】数据库建表实操!!
  • 【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表
  • 【Java】 —— 栈和队列
  • pytroch 使用神经网络来拟合异或操作
  • 气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型
  • 在深圳帮人做网站/个人网站怎么制作
  • 如何建立公司网站推广/郑州seo排名优化
  • 网站都需要续费吗/软文标题和内容
  • 做网站运营话术/百度服务电话
  • 软件公司的税收优惠政策/说说seo论坛
  • 电子商务网站建设的概要设计/合肥网络推广软件系统