Flutter for OpenHarmony:postgrest 直接访问 PostgreSQL 数据库的 RESTful 客户端(Supabase 核心驱动) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:postgrest 直接访问 PostgreSQL 数据库的 RESTful 客户端(Supabase 核心驱动) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

请添加图片描述

前言

如果你不想写复杂的 Java/Node.js 后端服务,只想直接增删改查数据库,PostgREST 是一个神奇的后端工具 —— 它能把从 PostgreSQL 数据库自动生成一套 RESTful API。而 postgrest (Dart库) 正是这一服务的官方客户端。

这也是 Supabase(Firebase 的开源替代品)的核心组件之一。通过它,你可以在 Flutter App 中像写 SQL 一样流畅地操作远程数据,既安全又高效。

一、概念介绍/原理解析

1.1 基础概念

  • Filter: eq('id', 1), gt('age', 18) 等,对应 SQL 的 WHERE
  • Select: 指定返回字段,支持关联查询(如 *, posts(*))。
  • Order: 排序规则。
  • RPC: 调用存储过程(Stored Procedures)。

HTTP 请求

SQL 语句

结果集

JSON 数据

Flutter 移动应用

PostgREST 接口网关

后台数据库

1.2 进阶概念

虽然看起来是直连数据库,但实际上通过 PostgREST 的 RLS (Row Level Security) 机制,你可以非常精细地控制每个用户只能读写自己的数据,无需担心越权。

二、核心 API/组件详解

2.1 基础用法

查询数据。

import'package:postgrest/postgrest.dart';final client =PostgrestClient('https://your-project.supabase.co/rest/v1');voidmain()async{// SELECT * FROM countries WHERE name = 'China'final data =await client .from('countries').select().eq('name','China');print(data);// List<Map<String, dynamic>>}
在这里插入图片描述

2.2 插入与更新

// INSERT INTO users (name, status) VALUES ('Tom', 'active')await client.from('users').insert({'name':'Tom','status':'active'});// UPDATE users SET status = 'inactive' WHERE id = 1await client.from('users').update({'status':'inactive'}).eq('id',1);
在这里插入图片描述

三、常见应用场景

3.1 场景 1:无后端 App

基于 Supabase 或自建 PostgREST,直接开发 CMS 或简单的社交应用。

// 获取文章列表及作者信息final posts =await client.from('posts').select('*, author:users(*)');
在这里插入图片描述

3.2 场景 2:实时排行榜

虽然 postgrest 主要是 REST,但结合 Realtime 功能(Supabase),可实现实时数据同步。

// 仅使用 postgrest 获取快照final top10 =await client.from('scores').select().order('score', ascending:false).limit(10);
在这里插入图片描述

3.3 场景 3:调用复杂业务逻辑

通过 RPC 调用数据库函数。

// 调用名为 "reset_password" 的函数await client.rpc('reset_password', params:{'email':'[email protected]'});
在这里插入图片描述

四、OpenHarmony 平台适配

4.1 网络请求库

postgrest 内部默认使用 http 库。在 OpenHarmony 上,这完全没问题。如果你需要自定义(比如加 Token 拦截器或使用 Dio),可以通过构造函数传入自定义 Client。

4.2 权限声明

同样别忘了在鸿蒙 config.json/module.json5 中声明 ohos.permission.INTERNET

五、完整示例代码

本示例列出所有任务 (Todos),并支持点击切换完成状态。

import'package:flutter/material.dart';import'package:postgrest/postgrest.dart';// 请替换为你自己的 PostgREST 服务地址constString _url ='https://my-project.supabase.co/rest/v1';constString _anonKey ='your-anon-key';// 如果有的话voidmain(){runApp(constMaterialApp(home:TodoPage()));}classTodoPageextendsStatefulWidget{constTodoPage({super.key});@overrideState<TodoPage>createState()=>_TodoPageState();}class _TodoPageState extendsState<TodoPage>{ late finalPostgrestClient _client;List<Map<String,dynamic>> _todos =[]; bool _loading =true;@overridevoidinitState(){super.initState(); _client =PostgrestClient( _url, headers:{'apikey': _anonKey},// 公钥);_fetchTodos();}Future<void>_fetchTodos()async{try{final res =await _client.from('todos').select().order('id');setState((){ _todos =List<Map<String,dynamic>>.from(res asList); _loading =false;});}catch(e){print('Error: $e');setState(()=> _loading =false);}}Future<void>_toggle(int id, bool current)async{// 乐观更新 UIfinal index = _todos.indexWhere((t)=> t['id']== id);if(index !=-1){setState((){ _todos[index]['is_complete']=!current;});}try{await _client.from('todos').update({'is_complete':!current}).eq('id', id);}catch(e){// 失败回滚..._fetchTodos();}}@overrideWidgetbuild(BuildContext context){returnScaffold( appBar:AppBar(title:constText('PostgREST Todos')), body: _loading ?constCenter(child:CircularProgressIndicator()):ListView.builder( itemCount: _todos.length, itemBuilder:(context, index){final todo = _todos[index];final isDone = todo['is_complete']as bool???false;returnCheckboxListTile( title:Text(todo['task']asString), value: isDone, onChanged:(_)=>_toggle(todo['id']as int, isDone),);},), floatingActionButton:FloatingActionButton( onPressed: _fetchTodos, child:constIcon(Icons.refresh),),);}}
在这里插入图片描述

六、总结

postgrest 极大地降低了全栈开发的门槛。前端开发者只需专注于 UI 和数据查询,复杂的后端逻辑交给强大的 PostgreSQL 数据库去处理。

最佳实践

  1. 安全性:永远不要在客户端使用 service_role 密钥(超级管理员权限)。始终使用 anon 密钥配合 RLS。
  2. 类型生成:手动解析 Map<String, dynamic> 很累且容易出错,建议使用 supabase_flutter 配合代码生成工具。

Read more

通过手势控制电脑的方案详细分析+python最小可运行示例(2026年最新)

通过手势控制电脑的方案详细分析+python最小可运行示例(2026年最新)

通过手势控制电脑的方案详细分析**(2026年最新) 手势控制电脑(Hand Gesture Control)属于自然人机交互(NUI)领域,已从科幻(《少数派报告》)走向实际应用。主流方案分为视觉识别(摄像头)、专用硬件、穿戴式三类,目前视觉方案 + MediaPipe 是性价比最高、最易落地的选择。 1. 主要技术方案分类与对比 方案类型代表技术/硬件精度延迟成本适用场景优缺点亮点普通摄像头视觉MediaPipe Hands + OpenCV高(2D)极低免费日常办公、DIY无需额外硬件,实时性强专用深度/红外摄像头Ultraleap Leap Motion 2极高(3D)极低100-200美元专业、VR/AR、演示3D追踪最强,抗遮挡好深度摄像头Intel RealSense / Kinect / Orbbec高低50-300美元研究、机器人提供深度信息,但部分已停产穿戴式传感器数据手套、IMU手环、EMG臂带中-高中中-高特定专业领域不依赖光线,但佩戴不便其他Google Soli雷达、超声波中低-手机集成体积小,

By Ne0inhk

用 Python 30 分钟做出自己的记事本

🌟 《零基础手把手:用 Python 30 分钟做出自己的记事本》 —— 不是照抄代码,而是理解每行代码的「灵魂」 🧩 第一步:为什么我们需要「基础窗口」?(新手必懂!) ❌ 常见错误:直接写 window.show() 但窗口不显示? ✅ 正确逻辑:程序运行流程图 启动程序 创建应用对象 创建窗口 显示窗口 进入事件循环 📝 代码详解(逐行解释): import sys # 必须!用于接收系统参数(比如文件路径)from PyQt6.QtWidgets import QApplication, QMainWindow # 从PyQt库导入两个核心组件# 1️⃣ 创建应用对象(灵魂!所有PyQt程序必须有) app = QApplication(sys.argv)# sys.argv = 系统传递的命令行参数(比如打开的文件名)

By Ne0inhk
Python 流程控制完全指南:条件语句 + 循环语句 + 实战案例(零基础入门)

Python 流程控制完全指南:条件语句 + 循环语句 + 实战案例(零基础入门)

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 顺序语句:基础执行语句 * 二. 条件语句:实现 “如果… 否则…” 逻辑 * 2.1 核心语法格式 * 2.2 关键注意点 * 2.3 空语句 pass:占位符作用 * 2.4 练习题 * 三. 循环语句:实现 “重复执行” 逻辑 * 3.1 while 循环:条件满足就一直执行 * 3.2 for 循环:

By Ne0inhk