Skip to content

Commit eb2292d

Browse files
committed
Add plugin model alembic support
1 parent 2c7ac5f commit eb2292d

File tree

9 files changed

+66
-19
lines changed

9 files changed

+66
-19
lines changed

backend/alembic/env.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616
from backend.common.model import MappedBase
1717
from backend.core import path_conf
1818
from backend.database.db import SQLALCHEMY_DATABASE_URL
19+
from backend.plugin.plugin import get_plugin_models
1920

2021
# import your new model here
2122
from backend.app.admin.model import * # noqa: F401
2223
from backend.app.generator.model import * # noqa: F401
2324

25+
# import plugin model
26+
for cls in get_plugin_models():
27+
class_name = cls.__name__
28+
if class_name in globals():
29+
print(f'\nWarning: Class "{class_name}" already exists in global namespace.')
30+
else:
31+
globals()[class_name] = cls
32+
2433
if not os.path.exists(path_conf.ALEMBIC_VERSION_DIR):
2534
os.makedirs(path_conf.ALEMBIC_VERSION_DIR)
2635

backend/app/admin/service/data_rule_service.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ async def get_models() -> list[str]:
4242
async def get_columns(model: str) -> list[str]:
4343
if model not in settings.DATA_PERMISSION_MODELS:
4444
raise errors.NotFoundError(msg='数据模型不存在')
45-
model_ins = dynamic_import(settings.DATA_PERMISSION_MODELS[model])
45+
try:
46+
model_ins = dynamic_import(settings.DATA_PERMISSION_MODELS[model])
47+
except (ImportError, AttributeError):
48+
raise errors.ServerError(msg=f'数据模型 {model} 动态导入失败,请联系系统超级管理员')
4649
model_columns = [
4750
key for key in model_ins.__table__.columns.keys() if key not in settings.DATA_PERMISSION_COLUMN_EXCLUDE
4851
]

backend/common/security/permission.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ def filter_data_permission(request: Request) -> ColumnElement[bool]:
6060
rule_model = rule.model
6161
if rule_model not in settings.DATA_PERMISSION_MODELS:
6262
raise errors.NotFoundError(msg='数据规则模型不存在')
63-
model_ins = dynamic_import(settings.DATA_PERMISSION_MODELS[rule_model])
63+
try:
64+
model_ins = dynamic_import(settings.DATA_PERMISSION_MODELS[rule_model])
65+
except (ImportError, AttributeError):
66+
raise errors.ServerError(msg=f'数据模型 {rule_model} 动态导入失败,请联系系统超级管理员')
6467
model_columns = [
6568
key for key in model_ins.__table__.columns.keys() if key not in settings.DATA_PERMISSION_COLUMN_EXCLUDE
6669
]

backend/core/path_conf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@
2222

2323
# jinja2 模版文件路径
2424
JINJA2_TEMPLATE_DIR = os.path.join(BasePath, 'templates')
25+
26+
# 插件目录
27+
PLUGIN_DIR = os.path.join(BasePath, 'plugin')

backend/plugin/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-

backend/plugin/conf.toml

Lines changed: 0 additions & 4 deletions
This file was deleted.

backend/plugin/notice/plugin.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# 插件名称
2-
name = 'notice'
31
# 是否对此插件启用 alembic
42
alembic = true
53

backend/plugin/plugin.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
import inspect
4+
import os
5+
6+
from backend.core.path_conf import PLUGIN_DIR
7+
from backend.utils.import_parse import import_module_cached
8+
9+
10+
def get_plugins() -> list[str]:
11+
"""获取插件"""
12+
plugin_packages = []
13+
14+
for item in os.listdir(PLUGIN_DIR):
15+
item_path = os.path.join(PLUGIN_DIR, item)
16+
17+
if os.path.isdir(item_path):
18+
if '__init__.py' in os.listdir(item_path):
19+
plugin_packages.append(item)
20+
21+
return plugin_packages
22+
23+
24+
def get_plugin_models():
25+
"""获取插件所有模型类"""
26+
classes = []
27+
plugins = get_plugins()
28+
for plugin in plugins:
29+
module_path = f'backend.plugin.{plugin}.model'
30+
module = import_module_cached(module_path)
31+
for name, obj in inspect.getmembers(module):
32+
if inspect.isclass(obj):
33+
classes.append(obj)
34+
return classes
35+
36+
37+
if __name__ == '__main__':
38+
print(get_plugins())
39+
print(get_plugin_models())

backend/utils/import_parse.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
from functools import lru_cache
66
from typing import Any
77

8-
from backend.common.exception import errors
98

10-
11-
def parse_module_str(module_path: str) -> tuple:
9+
def module_parse(module_path: str) -> tuple:
1210
"""
1311
Parse a module string into a Python module and class/function.
1412
@@ -37,11 +35,7 @@ def dynamic_import(module_path: str) -> Any:
3735
:param module_path:
3836
:return:
3937
"""
40-
module_name, obj_name = parse_module_str(module_path)
41-
42-
try:
43-
module = import_module_cached(module_name)
44-
class_or_func = getattr(module, obj_name)
45-
return class_or_func
46-
except (ImportError, AttributeError):
47-
raise errors.ServerError(msg=f'数据模型 {module_name} 动态导入失败,请联系系统超级管理员')
38+
module_name, class_or_func = module_parse(module_path)
39+
module = import_module_cached(module_name)
40+
ins = getattr(module, class_or_func)
41+
return ins

0 commit comments

Comments
 (0)