5分钟搭建 Supabase 数据库:从建表到 RLS 策略,为 Refine 管理后台备好后端
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
Supabase 是一款基于 PostgreSQL 的开源后端即服务(BaaS)平台,集数据库、认证、存储和自动生成 API 于一体。本指南完全围绕Supabase 数据库的搭建展开:创建项目、设计表结构、建立外键关系、插入示例数据,并最终启用 REST API 与行级安全(RLS)策略。读完本文,你将拥有一个可被 Refine 直接消费的、带关系与约束的生产级数据模型,为后续自动生成列表、创建、编辑等管理后台页面打好基础。
本文不涉及前端与 API 调用细节,只专注数据库侧的实操——这也是后续连接 Refine 时最重要的前置步骤。
Step 1:创建 Supabase 项目
打开 Supabase 官网,点击Start your project。你可以使用 GitHub 账号或任意邮箱登录。
进入 Dashboard 后,点击New project并填写以下信息:
| 配置项 | 说明 |
|---|---|
| Name | 项目名称,任意填写,例如team-admin |
| Password | 数据库密码,请务必妥善保存 |
| Region | 选择离你或你的用户最近的区域 |
点击Create new project后,大约 30 秒内,你就能得到一个运行在云端的 PostgreSQL 数据库,并且开箱即用地附带认证、存储和即时 API。
创建完成后会进入项目 Dashboard,核心功能区包括:
- Table Editor——以可视化方式管理数据库结构
- Authentication——添加用户与权限
- Storage——上传和管理文件
- Edge Functions——运行自定义后端逻辑
本指南的后续步骤都将在Table Editor中完成。
Step 2:认识 Table Editor
Table Editor 是设计数据模型的地方。你不需要写 SQL——当然也可以写——Supabase 提供了干净的 UI 让你可视化地定义一切。
每一张表都像一张电子表格,但带有类型、约束和关系。
创建新表时,你需要定义:
- 表名(Table name)
- 列(Columns,即字段)
- 数据类型(Data types:
text、integer、timestamp等) - 默认值与约束(Default values & constraints)
- 关系(Relationships,即外键)
Supabase 会在底层自动生成并处理对应的 SQL。你在 Table Editor 里构建的一切,都会立即通过 REST API 和 GraphQL 对外暴露(前提是策略允许,见下文 RLS 部分)。
Row Level Security(RLS)与策略速览
使用 Table Editor 创建表时,Row Level Security (RLS)默认是开启的。当 RLS 开启且没有任何策略(Policies)时,任何通过 REST 或 GraphQL API(使用公开的anon密钥)发起的请求都不会返回任何行。
策略(Policies)是 PostgreSQL 规则,它们相当于为每个操作(SELECT、INSERT、UPDATE、DELETE)隐式添加的WHERE子句。你需要在后面添加策略来有选择地开放访问。
角色映射关系如下:
anon:没有携带用户 JWT 的请求(仅使用公开密钥)authenticated:携带有效用户 JWT 的请求(包括通过 Supabase Auth 创建的"匿名会话",这些会话同样使用authenticated角色)
你可以随时在表的Policies标签页中查看或修改 RLS。本指南先聚焦表结构,等结构就绪后再添加策略。
Step 3:创建你的第一张表
我们来创建一张简单的employees表——这是后续在 Refine 中常见的资源类型。
- 在Table Editor中点击New Table。
- 命名为
employees。 - 添加以下列:
| Column | Type | Default | 说明 |
|---|---|---|---|
id | uuid | gen_random_uuid() | 主键 |
name | text | — | 员工姓名 |
role | text | — | 职位或头衔 |
salary | numeric(12,2) | — | 可选薪资字段(若需严格金额运算,建议用整数存储最小货币单位) |
created_at | timestamptz | now() | 记录创建时间 |
小提示:Table Editor 中的"Enable Row Level Security"开关默认是开启的。请保持开启状态——在添加显式策略之前,你的表都是受保护的。
点击Save后,表会被立即创建,并在策略允许的情况下通过 REST 对外可用。
Step 4:添加关联表
再创建一张departments表,用来演示关系(外键)是如何工作的。
- 点击New Table,命名为
departments。 - 添加:
| Column | Type | Default |
|---|---|---|
id | uuid | gen_random_uuid() |
name | text | — |
接下来回到employees表,点击Add Column,添加名为department_id的列:
- 类型设置为
uuid - 在Foreign Key下选择departments → id
- 为更安全的删除行为,将外键行为设置为ON DELETE SET NULL
再次点击Save。
至此,你建立了第一个关系:每个员工都属于一个部门。Supabase 会自动处理引用完整性并更新你的 schema。
这样的结构已经可以被 Refine 后续分析,并为你生成可用的列表、创建和编辑页面。
Step 5:插入示例数据
在Table Editor中点击departments表,选择Insert Row,添加几条示例数据:
| id | name |
|---|---|
| (auto) | Engineering |
| (auto) | Marketing |
| (auto) | HR |
然后进入employees表插入:
| id | name | role | salary | department_id |
|---|---|---|---|---|
| (auto) | Alice | Engineer | 85000 | (Engineering 的 id) |
| (auto) | Bob | HR Specialist | 60000 | (HR 的 id) |
现在你的数据已经上线。你可以直接在 Dashboard 中查看、编辑和筛选它们,也可以在SQL Editor标签页中用 SQL 查询。
Step 6:探索 SQL Editor
虽然 Table Editor 是可视化的,但 Supabase 同样支持完整的 PostgreSQL SQL。点击侧边栏的SQL Editor标签页即可。
在这里你可以:
- 运行查询,例如
SELECT * FROM employees; - 创建视图(views)、触发器(triggers)和函数(functions)
- 保存并对 SQL 脚本进行版本管理
例如,在插入了departments并用真实的department_id关联员工之后,试试这条查询:
SELECT e.name, e.role, d.name AS department FROM public.employees e LEFT JOIN public.departments d ON e.department_id = d.id;警告:Relation not found (42P01)如果看到
ERROR: 42P01: relation "public.employees" does not exist:
- 确认创建表时点击了 Save。
- 确认 schema 是
public(默认值)且表名为小写employees。- 刷新浏览器标签页——有时 SQL Editor 的元数据会滞后。
- 确认你正处于创建该表的同一项目中。
小提示:没有结果或 department 为 NULL?
LEFT JOIN会保留尚未设置department_id的员工。想看到部门名称,可以编辑员工记录,把正确部门的 UUID 粘贴到department_id字段中。
这种灵活性意味着你可以构建出 Refine(或任何前端)能直接使用的关联结构。
Step 7:启用 API 与策略
你在暴露的 schema 中创建的每张表都会自动获得一个 REST 端点,例如:
https://<project-ref>.supabase.co/rest/v1/employeesAPI 示例与密钥可以在Project Settings → API Docs中查看。
由于 RLS 是开启的,你必须先添加策略,数据才能对外可见。在表的Policies标签页中:
- 打开
employees→ Policies → New Policy。 - 选择操作:SELECT。
- 模板选择 "Allow authenticated users"(或自定义)。
- 保存。UI 会展示对应的 SQL 供参考。
生成的读策略如下:
create policy "Authenticated can read employees" on public.employees for select to authenticated using (true);插入策略(允许已认证用户添加行):
create policy "Enable insert for authenticated users only" on public.employees for insert to authenticated with check (true);可选(仅限开发环境)更宽泛的读访问:
create policy "Dev read employees (anon + authenticated)" on public.employees for select to anon, authenticated using (true);在生产环境前请务必移除这些宽松策略。
角色细节再强调一下:
- 没有 JWT 的请求使用
anon角色。 - 已认证的用户会话(包括 Supabase 的匿名认证会话)映射到
authenticated。 - 未认证请求的
auth.uid()为NULL——可以结合auth.uid() IS NOT NULL之类的检查来增强清晰度。
策略配置完成后,REST 调用示例:
curl -H "apikey: $SUPABASE_ANON_KEY" \ -H "Authorization: Bearer $USER_JWT" \ "https://<project-ref>.supabase.co/rest/v1/employees?select=*"之后你还可以叠加更细粒度的策略(行归属、基于角色的过滤等)。
仓库视角:Refine 如何消费这张 Supabase 数据库
数据库就绪后,把目光转回本仓库,看看 Refine 是如何消费这张表的。仓库中的 Supabase 集成包位于 packages/supabase,其入口 src/index.ts 统一导出了createClient、dataProvider与liveProvider三个核心能力:
import { dataProvider, liveProvider, createClient } from "@refinedev/supabase"; const supabaseClient = createClient("SUPABASE_URL", "SUPABASE_KEY"); const App = () => { return ( <Refine dataProvider={dataProvider(supabaseClient)} liveProvider={liveProvider(supabaseClient)} /* ... */ > {/* ... */} </Refine> ); };Data Provider:表结构直接映射为 CRUD 操作
在 packages/supabase/src/dataProvider/index.ts 中,dataProvider把getList、getOne、create、update、deleteOne等 Refine 数据方法翻译成对 Supabase 客户端链式查询的调用。几个值得关注的细节:
- 分页:
getList默认currentPage = 1、pageSize = 10、mode = "server",通过query.range()实现服务端分页(见 dataProvider/index.ts)。 - schema 支持:通过
meta.schema可切换非publicschema(supabaseClient.schema(meta.schema))。 - 关联查询:排序时可解析
foreignTable.field形式,实现跨表排序;示例中meta.select传入"*, categories(title)"即直接拉起关联字段。 - 过滤器映射:Refine 的
CrudFilter运算符由 generateFilter.ts 逐条转换为 Supabase 查询,例如contains→ilike('%value%')、between→gte(...).lte(...);运算符名映射见 mapOperator.ts。
Live Provider:基于 Postgres 实时变更订阅
packages/supabase/src/liveProvider/index.ts 利用 Supabase 的postgres_changes实时通道,把数据库中的INSERT/UPDATE/DELETE事件推送给 Refine 前端。它支持通过params.filters过滤订阅、通过params.ids只关注特定记录,并监听默认publicschema 下的指定表——也就是说,你在 Table Editor 里定义的表结构,天然就是实时订阅的订阅源。
开箱即用的示例项目
仓库中的 examples/data-provider-supabase 是一个可直接运行的完整示例,其 Supabase 客户端初始化见 src/utility/supabaseClient.ts,页面代码位于 src/pages/posts。以列表页 list.tsx 为例,它通过useTable的meta.select声明关联字段、配合useSelect加载分类下拉,展示了数据库关系如何直接映射成表格列、筛选器和表单选项。参考 README 运行示例:
npm create refine-app@latest -- --example contenteditable="false">【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.
项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考