superset详解(五)--视图生成

本文详细解析了Superset中的权限与视图生成机制,包括菜单视图、普通视图及资源视图的创建方式,特别关注了数据库与数据表的权限控制,通过SQLAlchemy与FlaskAppBuilder实现。

superset的权限和视图是不可分割的,下面我们来看看视图是怎么生成的。视图可以分为3类,菜单视图,普通视图(不生成菜单的视图,只添加链接),资源视图。
前2类视图是flaskappbuilder控制生成的,后一种视图是sqlalchemy控制生成的。


菜单视图/非菜单视图生成

appbuilder.add_view() 生成菜单视图
appbulier.add_view_no_menu()   生成没有菜单的视图

flask_appbuilder/security/manage.py
    def add_permissions_view(self, base_permissions, view_menu):
        view_menu_db = self.add_view_menu(view_menu)   # 把视图添加到视图表中
        pass

资源视图

superset的资源视图主要是数据库,数据表

数据库权限:
sqla.event.listen(Database, 'after_insert', set_perm)
sqla.event.listen(Database, 'after_update', set_perm)

def get_perm(self):
    return (
        '[{obj.database_name}].(id:{obj.id})').format(obj=self)  

sqlalchemy设置了插入和更新的监听事件,当这些时间发生的时候,就会把改资源对应的视图插入到数据表中。可以看到数据库的视图是由数据库的名字和它的ID组成的

数据表权限:
sa.event.listen(SqlaTable, 'after_insert', set_perm)
sa.event.listen(SqlaTable, 'after_update', set_perm)

def get_perm(self):
      return (
          '[{obj.database}].[{obj.table_name}]'
          '(id:{obj.id})').format(obj=self)

表资源视图的插入和数据库资源视图的插入机制一样,只是视图不一样,表资源的视图是由数据库的名字,表的名字和表的ID组成

gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker compose down --volumes --remove-orphans [+] Running 7/7 ✔ Container superset-web Removed 0.0s ✔ Container superset-prod-superset-init-1 Removed 1.3s ✔ Container superset-prod-redis-1 Removed 0.3s ✔ Container superset-prod-mysql-1 Removed 1.0s ✔ Volume superset-prod_mysql_data Removed 0.0s ✔ Network superset-prod_superset-net Removed 0.4s ✔ Volume superset-prod_redis_data Removed 0.0s gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker system prune -f Total reclaimed space: 0B gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker compose down -v gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker compose up -d [+] Running 7/7 ✔ Network superset-prod_superset-net Created 0.0s ✔ Volume superset-prod_mysql_data Created 0.0s ✔ Volume superset-prod_redis_data Created 0.0s ✔ Container superset-prod-redis-1 Healthy 6.0s ✔ Container superset-prod-mysql-1 Healthy 16.0s ✔ Container superset-prod-superset-init-1 Started 16.1s ✔ Container superset-web Started 16.2s gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker logs -f superset-init Error response from daemon: No such container: superset-init gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS superset-prod-mysql-1 mysql:8.0 "docker-entrypoint.s…" mysql 40 seconds ago Up 39 seconds (healthy) 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp superset-prod-redis-1 redis:7-alpine "docker-entrypoint.s…" redis 40 seconds ago Up 39 seconds (healthy) 6379/tcp superset-prod-superset-init-1 apache/superset:latest "bash -c '\n echo '…" superset-init 40 seconds ago Up 24 seconds (health: starting) 8088/tcp superset-web apache/superset:latest "bash -c '\n pip ins…" superset 40 seconds ago Restarting (2) 3 seconds ago gapinyc@DESKTOP-9QS7RL5:~/superset-prod$ 没有成功,到底是哪里的问题导致的呢
最新发布
10-22
你已经执行了完整的清理和重建流程: ```bash docker compose down --volumes --remove-orphans docker compose up -d ``` 但 `docker logs -f superset-init` 报错: ``` Error response from daemon: No such container: superset-init ``` 而 `docker compose ps` 显示: ``` NAME STATUS superset-prod-superset-init-1 Up 24 seconds (health: starting) superset-web Restarting (2) 3 seconds ago ``` --- ## 🔍 关键线索分析 ### ✅ 正确认知:容器名不是 `superset-init`,而是 `superset-prod-superset-init-1` 你在用错误的名字查日志! Docker Compose 自动生成的容器名是: ``` <项目目录名>-<服务名>-<序号> → superset-prod-superset-init-1 ``` 所以你应该运行: ```bash docker logs -f superset-prod-superset-init-1 ``` 而不是: ```bash docker logs -f superset-init ❌ 错误!不存在这个容器 ``` --- ## ✅ 第一步:查看正确的容器日志 ```bash # 查看 superset-init 容器的真实日志 docker logs -f superset-prod-superset-init-1 ``` 你会看到类似输出: ``` 🚀 Starting superset-init... ⏳ Waiting for MySQL (mysql:3306)... ✅ MySQL is reachable. ✅ Redis is reachable. 🔧 Creating admin user... Error: Invalid login_type public for user admin ``` 或者: ``` superset db upgrade sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (2002, "Can't connect to MySQL server on 'mysql' (115)") ``` 📌 **只有通过这个命令才能看到真实错误!** --- ## ✅ 第二步:为什么 `superset-web` 在不断重启? ```bash Restarting (2) 3 seconds ago ``` 说明 `superset-web` 启动失败并被 `restart: unless-stopped` 不断拉起。 查看它的日志: ```bash docker logs -f superset-web ``` 常见错误: - 缺少 `pymysql` → `ModuleNotFoundError: No module named 'pymysql'` - 数据库连接失败 → `Can't connect to MySQL server` - 元数据库未初始化 → `Table 'superset.ab_user' doesn't exist` --- ## 🚨 核心问题推断(基于你的状态) | 现象 | 推断 | |------|------| | `superset-prod-superset-init-1` 运行中但没完成 | 初始化脚本卡在某个步骤(如等 DB)或报错后继续 | | `superset-web` 不断重启 | 它依赖的数据库未准备好,或缺少依赖 | | 你无法用 `superset-init` 查日志 | 容器名错误 | --- ## ✅ 正确调试流程 ### 1. 查看 `superset-init` 的真实日志 ```bash docker logs -f superset-prod-superset-init-1 ``` 如果看到: ``` while ! nc -z mysql 3306; do echo '🔴 MySQL is not reachable yet...' done; ``` 并且一直循环 → 说明 **网络不通或 DNS 解析失败** --- ### 2. 测试网络连通性(关键!) 进入 `superset-init` 容器测试: ```bash # 进入容器 docker exec -it superset-prod-superset-init-1 sh # 测试 DNS 解析 nslookup mysql # 应该返回 IP 地址,例如: # Name: mysql # Address: 172.18.0.3 # 如果报错:nslookup: command not found → 没有安装 dns 工具包 # 测试端口连通 nc -z mysql 3306 && echo "OK" || echo "FAIL" ``` 如果 `nc` 不存在,先安装: ```bash apt-get update && apt-get install -y netcat-openbsd ``` --- ### 3. 查看 `superset-web` 日志 ```bash docker logs superset-web ``` 典型错误: #### ❌ 错误 1:缺少 pymysql ``` ModuleNotFoundError: No module named 'pymysql' ``` **解决方法**:在 `command` 中加安装命令: ```yaml command: > bash -c " pip install PyMySQL > /dev/null 2>&1; python -c 'import pymysql; pymysql.install_as_MySQLdb()' || true; gunicorn ... " ``` #### ❌ 错误 2:数据库表不存在 ``` Table 'superset.ab_user' doesn't exist ``` 说明 `superset-init` 虽然运行了,但: - `superset db upgrade` 失败 - 或者没有真正写入数据库 --- ## ✅ 终极修复建议:确保 `superset-init` 成功完成后再启动 `superset-web` 修改 `docker-compose.yml`: ```yaml superset: depends_on: superset-init: condition: service_completed_successfully ``` 完整写法: ```yaml superset: # ... 其他配置 depends_on: superset-init: condition: service_completed_successfully ``` 这表示:**只有当 `superset-init` 成功退出(exit 0)后,才启动 `superset-web`** 否则就会出现“web 先启动,数据库还没初始化”的竞争条件。 --- ## ✅ 推荐最终版 `superset-init` 配置(防错增强) ```yaml superset-init: image: apache/superset:latest depends_on: mysql: condition: service_healthy redis: condition: service_healthy environment: - DATABASE_URL=mysql+pymysql://superset_user:superset_password@mysql:3306/superset command: > bash -c " set -ex # 关键:出错立即停止并显示命令 echo '📦 Installing dependencies...' apt-get update > /dev/null apt-get install -y netcat-openbsd > /dev/null echo '⏳ Waiting for MySQL...' until nc -z mysql 3306; do sleep 3; done echo '⏳ Waiting for Redis...' until nc -z redis 6379; do sleep 3; done echo '📦 Installing PyMySQL...' pip install PyMySQL python -c 'import pymysql; pymysql.install_as_MySQLdb()' echo '🔧 Creating admin...' superset fab create-admin \ --username admin \ --firstname Admin \ --lastname User \ --email admin@example.com \ --password admin echo '🗄 Database upgrade...' superset db upgrade echo '📊 Load examples...' superset load_examples echo '🎉 Init...' superset init echo '✅ Success!' " networks: - superset-net # 注意:不要加 restart: on-failure,否则会掩盖错误 ``` > ⚠️ `set -ex`:让脚本在任何命令失败时退出,并打印每条命令,便于调试 --- ## ✅ 总结:你现在应该做的事 1. ✅ 使用正确容器名查看日志: ```bash docker logs -f superset-prod-superset-init-1 ``` 2. ✅ 检查是否安装了 `netcat-openbsd` 并能连通 `mysql:3306` 3. ✅ 确保 `superset-web` 等待 `superset-init` 成功完成 4. ✅ 在 `superset-web` 和 `superset-init` 中都安装 `PyMySQL` 5. ✅ 加上 `set -ex` 让脚本失败时暴露错误 --- ## 🧪 示例:成功后的预期行为 ```bash docker logs superset-prod-superset-init-1 ``` 输出结尾应为: ``` + echo '✅ Success!' ✅ Success! ``` 然后容器退出:`Exit 0` 接着 `superset-web` 启动,不再重启,访问 `http://localhost:8088` 成功登录。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值