valar 1.1.4__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of valar might be problematic. Click here for more details.
- valar/apps.py +6 -9
- valar/channels/consumer.py +10 -12
- valar/channels/executer.py +7 -6
- valar/channels/sender.py +95 -43
- valar/channels/views.py +2 -3
- valar/classes/{auto_migration_mixin.py → app_mixins/auto_migration_mixin.py} +2 -2
- valar/classes/{auto_urlpatterns_mixin.py → app_mixins/auto_urlpatterns_mixin.py} +3 -3
- valar/classes/valar_minio.py +80 -0
- valar/classes/valar_response.py +2 -1
- valar/dao/__init__.py +45 -0
- valar/dao/abstract.py +106 -0
- valar/dao/defaults/__init__.py +0 -0
- valar/dao/defaults/field_keys_default.py +48 -0
- valar/dao/defaults/field_values_default.py +135 -0
- valar/dao/defaults/view_defaults.py +26 -0
- valar/dao/engine.py +80 -0
- valar/dao/frame.py +189 -0
- valar/dao/meta.py +128 -0
- valar/dao/mon_dao.py +113 -0
- valar/dao/mon_field.py +23 -0
- valar/dao/orm_dao.py +304 -0
- valar/dao/orm_field.py +142 -0
- valar/dao/query.py +36 -0
- valar/migrations/0001_initial.py +25 -17
- valar/models/core.py +16 -10
- valar/models/frame.py +4 -7
- valar/models/meta.py +19 -16
- valar/urls.py +22 -0
- valar/views/file.py +49 -0
- valar/views/handler.py +33 -0
- valar/views/meta.py +150 -0
- valar/views/rest.py +90 -0
- {valar-1.1.4.dist-info → valar-1.2.1.dist-info}/METADATA +9 -14
- valar-1.2.1.dist-info/RECORD +54 -0
- {valar-1.1.4.dist-info → valar-1.2.1.dist-info}/top_level.txt +1 -0
- vtest/__init__.py +0 -0
- vtest/apps.py +17 -0
- vtest/handlers.py +15 -0
- vtest/migrations/0001_initial.py +155 -0
- vtest/migrations/__init__.py +0 -0
- vtest/models.py +59 -0
- vtest/views.py +8 -0
- valar-1.1.4.dist-info/RECORD +0 -28
- /valar/{classes → channels}/counter.py +0 -0
- /valar/{frame → classes/app_mixins}/__init__.py +0 -0
- {valar-1.1.4.dist-info → valar-1.2.1.dist-info}/WHEEL +0 -0
- {valar-1.1.4.dist-info → valar-1.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
meta_field_value_defaults = {
|
|
2
|
+
'valar.Meta': {
|
|
3
|
+
"__init__": {
|
|
4
|
+
"db": {
|
|
5
|
+
"tool": "set",
|
|
6
|
+
"format": {
|
|
7
|
+
"set": {
|
|
8
|
+
'orm': 'SQL',
|
|
9
|
+
'mon': 'MongoDB',
|
|
10
|
+
'center': '剧中对齐',
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
'valar.MetaView': {
|
|
17
|
+
"__init__": {
|
|
18
|
+
"meta_id": {
|
|
19
|
+
'allow_edit': False,
|
|
20
|
+
},
|
|
21
|
+
"code": {
|
|
22
|
+
'allow_edit': False,
|
|
23
|
+
},
|
|
24
|
+
"name": {
|
|
25
|
+
'span': 24
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"core": {
|
|
29
|
+
"name": {
|
|
30
|
+
'span': 16
|
|
31
|
+
},
|
|
32
|
+
"enable": {
|
|
33
|
+
"span": 8
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
'valar.MetaFieldDomain': {
|
|
38
|
+
"__init__": {
|
|
39
|
+
"default_id": {
|
|
40
|
+
"tool": "tree"
|
|
41
|
+
},
|
|
42
|
+
"search_id": {
|
|
43
|
+
"tool": "tree"
|
|
44
|
+
},
|
|
45
|
+
"tools": {
|
|
46
|
+
"tool": "tree",
|
|
47
|
+
"refer": {
|
|
48
|
+
"display": "code"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"align": {
|
|
52
|
+
"tool": "set",
|
|
53
|
+
"format": {
|
|
54
|
+
"set": {
|
|
55
|
+
'left': '左对齐',
|
|
56
|
+
'right': '右对齐',
|
|
57
|
+
'center': '剧中对齐',
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
'valar.MetaField': {
|
|
64
|
+
"rest": {
|
|
65
|
+
"name": {
|
|
66
|
+
'hide_on_form': False
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
"__init__": {
|
|
70
|
+
"column_width": {
|
|
71
|
+
'unit': 'px'
|
|
72
|
+
},
|
|
73
|
+
"name": {
|
|
74
|
+
'span': 24,
|
|
75
|
+
'hide_on_form': True
|
|
76
|
+
},
|
|
77
|
+
"fixed": {
|
|
78
|
+
"tool": "set",
|
|
79
|
+
"format": {
|
|
80
|
+
"set": {
|
|
81
|
+
'left': '左侧固定',
|
|
82
|
+
'right': '右侧固定',
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"align": {
|
|
87
|
+
"tool": "set",
|
|
88
|
+
"format": {
|
|
89
|
+
"set": {
|
|
90
|
+
'left': '左对齐',
|
|
91
|
+
'right': '右对齐',
|
|
92
|
+
'center': '剧中对齐',
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"prop": {
|
|
97
|
+
'allow_edit': False,
|
|
98
|
+
'column_width': 120
|
|
99
|
+
},
|
|
100
|
+
"domain": {
|
|
101
|
+
'allow_edit': False,
|
|
102
|
+
'column_width': 120,
|
|
103
|
+
},
|
|
104
|
+
"tool": {
|
|
105
|
+
'column_width': 100,
|
|
106
|
+
'span': 24,
|
|
107
|
+
'tool': 'tree',
|
|
108
|
+
'refer': {
|
|
109
|
+
'entity': 'valar.MetaFieldTool',
|
|
110
|
+
'includes': {'metafielddomain__name': '${domain}'},
|
|
111
|
+
'value': 'code', 'display': 'code', "isTree": True
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
},
|
|
115
|
+
"span": {
|
|
116
|
+
'column_width': 100,
|
|
117
|
+
"format": {"min": 0, "max": 24, "step": 1, "precision": 0, "step_strictly": True}
|
|
118
|
+
},
|
|
119
|
+
"refer": {
|
|
120
|
+
'allow_edit': False,
|
|
121
|
+
'column_width': 80
|
|
122
|
+
},
|
|
123
|
+
"format": {
|
|
124
|
+
'allow_edit': False,
|
|
125
|
+
'column_width': 80
|
|
126
|
+
},
|
|
127
|
+
'header_color': {
|
|
128
|
+
'tool': 'color',
|
|
129
|
+
},
|
|
130
|
+
'cell_color': {
|
|
131
|
+
'tool': 'color',
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
meta_view_default_values = {
|
|
2
|
+
'valar.Meta': {
|
|
3
|
+
'__init__': {
|
|
4
|
+
'allow_insert': False,
|
|
5
|
+
'allow_upload': False,
|
|
6
|
+
'lock': True
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
'valar.MetaView': {
|
|
10
|
+
'__init__': {
|
|
11
|
+
'allow_insert': False,
|
|
12
|
+
'allow_upload': False,
|
|
13
|
+
'lock': True
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
'valar.MetaField': {
|
|
17
|
+
'__init__': {
|
|
18
|
+
'allow_insert': False,
|
|
19
|
+
'allow_upload': False,
|
|
20
|
+
'lock': True
|
|
21
|
+
},
|
|
22
|
+
'tool': {
|
|
23
|
+
'allow_edit_on_form': False,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
valar/dao/engine.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import pymongo
|
|
2
|
+
from django.apps import apps
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
from minio import Minio
|
|
6
|
+
from pymongo.synchronous.collection import Collection
|
|
7
|
+
|
|
8
|
+
from ..classes.singleton_meta import SingletonMeta
|
|
9
|
+
from ..classes.valar_minio import ValarMinio
|
|
10
|
+
from ..models.core import VModel, VTree
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ValarEngine(metaclass=SingletonMeta):
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
orm_engine = {}
|
|
17
|
+
for model in apps.get_models():
|
|
18
|
+
meta = getattr(model, '_meta')
|
|
19
|
+
app = meta.app_label
|
|
20
|
+
if app not in ['sessions']:
|
|
21
|
+
entity = f'{app}.{model.__name__}'
|
|
22
|
+
orm_engine[entity] = model
|
|
23
|
+
self.orm_engine = orm_engine
|
|
24
|
+
|
|
25
|
+
# mon
|
|
26
|
+
if hasattr(settings, 'MONGO_URI'):
|
|
27
|
+
self.mongo_client = pymongo.MongoClient(
|
|
28
|
+
settings.MONGO_URI,
|
|
29
|
+
**{
|
|
30
|
+
'maxPoolSize': 10,
|
|
31
|
+
'minPoolSize': 0,
|
|
32
|
+
'maxIdleTimeMS': 10000,
|
|
33
|
+
'connectTimeoutMS': 10000,
|
|
34
|
+
'socketTimeoutMS': 10000,
|
|
35
|
+
'serverSelectionTimeoutMS': 10000,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
self.mongo_engine = self.mongo_client[settings.BASE_APP]
|
|
39
|
+
else:
|
|
40
|
+
self.mongo_client = None
|
|
41
|
+
self.mongo_engine = None
|
|
42
|
+
|
|
43
|
+
# minio
|
|
44
|
+
if hasattr(settings, 'MINIO_URL'):
|
|
45
|
+
parsed = urlparse(settings.MINIO_URL)
|
|
46
|
+
endpoint = f'{parsed.hostname}:{parsed.port}'
|
|
47
|
+
access_key = parsed.username
|
|
48
|
+
secret_key = parsed.password
|
|
49
|
+
self.minio_engine = Minio(
|
|
50
|
+
endpoint=endpoint,
|
|
51
|
+
access_key=access_key,
|
|
52
|
+
secret_key=secret_key,
|
|
53
|
+
secure=False
|
|
54
|
+
)
|
|
55
|
+
else:
|
|
56
|
+
self.minio_engine = None
|
|
57
|
+
|
|
58
|
+
def get_orm_model(self, entity) -> VModel:
|
|
59
|
+
return self.orm_engine[entity]
|
|
60
|
+
|
|
61
|
+
def get_mongo_collection(self, entity) -> Collection:
|
|
62
|
+
return self.mongo_engine[entity]
|
|
63
|
+
|
|
64
|
+
def get_minio_bucket(self, entity):
|
|
65
|
+
return ValarMinio(self.minio_engine, entity) if self.minio_engine else None
|
|
66
|
+
|
|
67
|
+
# def meta_tree(self):
|
|
68
|
+
# mapping = {}
|
|
69
|
+
# names = self.mongo_engine.list_collection_names()
|
|
70
|
+
#
|
|
71
|
+
# for entity, model in self.orm_engine.items():
|
|
72
|
+
# app, value = entity.split('.')
|
|
73
|
+
# is_tree = issubclass(model, VTree)
|
|
74
|
+
# meta = getattr(model, '_meta')
|
|
75
|
+
# name = meta.verbose_name
|
|
76
|
+
#
|
|
77
|
+
# node = mapping.get(app, {'label': app, 'value': app, 'db': 'orm', 'children': []})
|
|
78
|
+
# node['children'].append({"label": name, "value": value, 'isTree': is_tree})
|
|
79
|
+
# mapping[app] = node
|
|
80
|
+
# return list(mapping.values())
|
valar/dao/frame.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
from ..classes.singleton_meta import SingletonMeta
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MetaFrame(metaclass=SingletonMeta):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
from .orm_dao import OrmDao
|
|
9
|
+
from .meta import ValarMeta
|
|
10
|
+
from ..models.core import VTree
|
|
11
|
+
from .engine import ValarEngine
|
|
12
|
+
tool_dao = OrmDao('valar.MetaFieldTool')
|
|
13
|
+
domain_dao = OrmDao('valar.MetaFieldDomain')
|
|
14
|
+
tool_dao.delete()
|
|
15
|
+
domain_dao.delete()
|
|
16
|
+
mapping = {}
|
|
17
|
+
for item in meta_field_tool:
|
|
18
|
+
item = copy.deepcopy(item)
|
|
19
|
+
_id, code = item['id'], item['code']
|
|
20
|
+
item.update({"saved": True})
|
|
21
|
+
if item['isLeaf']:
|
|
22
|
+
mapping[code] = _id
|
|
23
|
+
tool_dao.save_one(item, True)
|
|
24
|
+
for row in meta_field_domain:
|
|
25
|
+
row = copy.deepcopy(row)
|
|
26
|
+
default_id, tools = row['default_id'], row['tools']
|
|
27
|
+
_row = copy.deepcopy(row)
|
|
28
|
+
_row.update({
|
|
29
|
+
'default_id': mapping[default_id],
|
|
30
|
+
'tools': [mapping[tool] for tool in tools],
|
|
31
|
+
"saved": True
|
|
32
|
+
})
|
|
33
|
+
domain_dao.save_one(_row)
|
|
34
|
+
|
|
35
|
+
meta_dao = OrmDao('valar.Meta')
|
|
36
|
+
meta_dao.delete([{"includes": {'db__exact': 'orm', 'entity__startswith': 'valar.'}}])
|
|
37
|
+
engine = ValarEngine()
|
|
38
|
+
for entity, model in engine.orm_engine.items():
|
|
39
|
+
tree = issubclass(model, VTree)
|
|
40
|
+
ValarMeta('orm', entity, 'default')
|
|
41
|
+
cols = engine.mongo_engine.list_collections()
|
|
42
|
+
for col in cols:
|
|
43
|
+
entity = col['name']
|
|
44
|
+
ValarMeta('mon', entity, 'default')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
meta_field_tool = [
|
|
48
|
+
{'id': 2, 'sort': 32, 'pid': 7, 'isLeaf': True, 'name': '输入框', 'code': 'text', 'align': 'left'},
|
|
49
|
+
{'id': 3, 'sort': 17, 'pid': 0, 'isLeaf': False, 'name': 'SPEC', 'code': '特殊工具集'},
|
|
50
|
+
{'id': 5, 'sort': 22, 'pid': 0, 'isLeaf': False, 'name': 'DATE', 'code': '日期时间工具集'},
|
|
51
|
+
{'id': 6, 'sort': 21, 'pid': 8, 'isLeaf': True, 'name': '数字输入', 'code': 'number', 'align': 'right'},
|
|
52
|
+
{'id': 7, 'sort': 36, 'pid': 0, 'isLeaf': False, 'name': 'TEXT', 'code': '文本工具集'},
|
|
53
|
+
{'id': 8, 'sort': 26, 'pid': 0, 'isLeaf': False, 'name': 'NUMB', 'code': '数字工具集'},
|
|
54
|
+
{'id': 9, 'sort': 10, 'pid': 0, 'isLeaf': False, 'name': 'FILE', 'code': '文件工具集'},
|
|
55
|
+
{'id': 10, 'sort': 27, 'pid': 0, 'isLeaf': False, 'name': 'BOOL', 'code': '逻辑工具集'},
|
|
56
|
+
{'id': 11, 'sort': 31, 'pid': 0, 'isLeaf': False, 'name': 'LIST', 'code': '列表工具集'},
|
|
57
|
+
{'id': 12, 'sort': 8, 'pid': 3, 'isLeaf': True, 'name': '对象', 'code': 'object', 'align': 'center'},
|
|
58
|
+
{'id': 13, 'sort': 5, 'pid': 9, 'isLeaf': True, 'name': '图片上传', 'code': 'image', 'align': 'center'},
|
|
59
|
+
{'id': 14, 'sort': 2, 'pid': 9, 'isLeaf': True, 'name': '文件上传', 'code': 'file', 'align': 'center'},
|
|
60
|
+
{'id': 15, 'sort': 13, 'pid': 7, 'isLeaf': True, 'name': '富文本', 'code': 'rich', 'align': 'center'},
|
|
61
|
+
{'id': 17, 'sort': 11, 'pid': 10, 'isLeaf': True, 'name': '开关', 'code': 'switch', 'align': 'center'},
|
|
62
|
+
{'id': 19, 'sort': 9, 'pid': 7, 'isLeaf': True, 'name': '颜色选择', 'code': 'color', 'align': 'center'},
|
|
63
|
+
{'id': 20, 'sort': 14, 'pid': 11, 'isLeaf': True, 'name': '穿梭框', 'code': 'transfer', 'align': 'left'},
|
|
64
|
+
{'id': 21, 'sort': 16, 'pid': 7, 'isLeaf': True, 'name': '自动填充', 'code': 'auto', 'align': 'left'},
|
|
65
|
+
{'id': 22, 'sort': 35, 'pid': 5, 'isLeaf': True, 'name': '日期选择', 'code': 'date', 'align': 'left'},
|
|
66
|
+
{'id': 23, 'sort': 12, 'pid': 10, 'isLeaf': True, 'name': '逻辑选择', 'code': 'boolean', 'align': 'center'},
|
|
67
|
+
{'id': 24, 'sort': 24, 'pid': 11, 'isLeaf': True, 'name': '列表选择', 'code': 'select', 'align': 'left'},
|
|
68
|
+
{'id': 25, 'sort': 15, 'pid': 11, 'isLeaf': True, 'name': '树形选择', 'code': 'tree', 'align': 'left'},
|
|
69
|
+
{'id': 26, 'sort': 23, 'pid': 11, 'isLeaf': True, 'name': '及联选择', 'code': 'cascade', 'align': 'left'},
|
|
70
|
+
{'id': 28, 'sort': 25, 'pid': 7, 'isLeaf': True, 'name': '图标', 'code': 'icon', 'align': 'center'},
|
|
71
|
+
{'id': 32, 'sort': 30, 'pid': 7, 'isLeaf': True, 'name': '文本框', 'code': 'textarea', 'align': 'left'},
|
|
72
|
+
{'id': 33, 'sort': 18, 'pid': 36, 'isLeaf': True, 'name': '时间区间', 'code': 'timerange', 'align': 'left'},
|
|
73
|
+
{'id': 35, 'sort': 33, 'pid': 5, 'isLeaf': True, 'name': '时间选择', 'code': 'time', 'align': 'left'},
|
|
74
|
+
{'id': 36, 'sort': 20, 'pid': 0, 'isLeaf': False, 'name': 'RANGE', 'code': '区间工具集'},
|
|
75
|
+
{'id': 37, 'sort': 38, 'pid': 36, 'isLeaf': True, 'name': '日期区间', 'code': 'daterange', 'align': 'left'},
|
|
76
|
+
{'id': 39, 'sort': 3, 'pid': 36, 'isLeaf': True, 'name': '多日期', 'code': 'dates', 'align': 'left'},
|
|
77
|
+
{'id': 54, 'sort': 54, 'pid': 7, 'isLeaf': True, 'name': '集合', 'code': 'set', 'align': 'left'},
|
|
78
|
+
{'id': 31, 'sort': 6, 'pid': 0, 'isLeaf': True, 'name': '无', 'code': 'none', 'align': 'left'},
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
meta_field_tool_mapping = {
|
|
82
|
+
row['code']: row['align']
|
|
83
|
+
for row in meta_field_tool
|
|
84
|
+
if row['isLeaf']
|
|
85
|
+
}
|
|
86
|
+
meta_field_domain = [
|
|
87
|
+
{
|
|
88
|
+
'name': 'CharField',
|
|
89
|
+
'default_id': 'text',
|
|
90
|
+
'tools': [
|
|
91
|
+
'text', 'number', 'color', 'auto', 'date', 'time', 'select', 'tree', 'cascade', 'icon',
|
|
92
|
+
'textarea', 'timerange', 'daterange', 'dates', 'set'
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
'name': 'TextField',
|
|
97
|
+
'default_id': 'textarea',
|
|
98
|
+
'tools': ['text', 'textarea', 'rich']
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
'name': 'BooleanField',
|
|
102
|
+
'default_id': 'switch',
|
|
103
|
+
'tools': ['switch', 'boolean']
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
'name': 'IntegerField',
|
|
107
|
+
'default_id': 'number',
|
|
108
|
+
'tools': ['number']
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
'name': 'FloatField',
|
|
112
|
+
'default_id': 'number',
|
|
113
|
+
'tools': ['number']
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
'name': 'ForeignKey',
|
|
117
|
+
'default_id': 'select',
|
|
118
|
+
'tools': ['select', 'tree', 'cascade']
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
'name': 'ManyToOneRel',
|
|
122
|
+
'default_id': 'select',
|
|
123
|
+
'tools': ['transfer', 'select', 'tree', 'cascade']
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
'name': 'ManyToManyField',
|
|
127
|
+
'default_id': 'select',
|
|
128
|
+
'tools': ['transfer', 'select', 'tree', 'cascade']
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
'name': 'ManyToManyRel',
|
|
132
|
+
'default_id': 'select',
|
|
133
|
+
'tools': ['transfer', 'select', 'tree', 'cascade']
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
'name': 'OneToOneRel',
|
|
137
|
+
'default_id': 'select',
|
|
138
|
+
'tools': ['select']
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
'name': 'OneToOneField',
|
|
142
|
+
'default_id': 'select',
|
|
143
|
+
'tools': ['select']
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
'name': 'DateField',
|
|
147
|
+
'default_id': 'date',
|
|
148
|
+
'tools': ['date']
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
'name': 'TimeField',
|
|
152
|
+
'default_id': 'time',
|
|
153
|
+
'tools': ['time']
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
'name': 'DateTimeField',
|
|
157
|
+
'default_id': 'date',
|
|
158
|
+
'tools': ['date']
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
'name': 'JSONField',
|
|
162
|
+
'default_id': 'object',
|
|
163
|
+
'tools': ['object']
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
'name': 'FileField',
|
|
167
|
+
'default_id': 'file',
|
|
168
|
+
'tools': ['image', 'file']
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
'name': 'BigAutoField',
|
|
172
|
+
'default_id': 'none',
|
|
173
|
+
'tools': ['none']
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
'name': 'UUIDField',
|
|
177
|
+
'default_id': 'none',
|
|
178
|
+
'tools': ['none']
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
'name': 'Custom',
|
|
182
|
+
'default_id': 'none',
|
|
183
|
+
'tools': ['none']
|
|
184
|
+
},
|
|
185
|
+
]
|
|
186
|
+
meta_field_domain_mapping = {
|
|
187
|
+
row['name']: row['default_id']
|
|
188
|
+
for row in meta_field_domain
|
|
189
|
+
}
|
valar/dao/meta.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
from deepmerge import always_merger
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
|
|
6
|
+
from ..dao.defaults.field_keys_default import meta_field_key_defaults
|
|
7
|
+
from ..dao.defaults.field_values_default import meta_field_value_defaults
|
|
8
|
+
from ..dao.defaults.view_defaults import meta_view_default_values
|
|
9
|
+
from ..dao.abstract import AbstractDao
|
|
10
|
+
from ..dao.frame import meta_field_tool_mapping
|
|
11
|
+
from ..dao.mon_dao import MonDao
|
|
12
|
+
from ..dao.orm_dao import OrmDao
|
|
13
|
+
from ..dao.orm_field import column_width
|
|
14
|
+
from ..models.frame import MetaFieldDomain
|
|
15
|
+
from ..models.meta import Meta, MetaView
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ValarMeta:
|
|
19
|
+
def __init__(self, db, entity, code):
|
|
20
|
+
self.entity = entity
|
|
21
|
+
self.db = db
|
|
22
|
+
self.dao: AbstractDao = MonDao(entity) if db == 'mon' else OrmDao(entity)
|
|
23
|
+
self.code = code or 'default'
|
|
24
|
+
|
|
25
|
+
meta_dao = OrmDao('valar.Meta')
|
|
26
|
+
view_dao = OrmDao('valar.MetaView')
|
|
27
|
+
field_dao = OrmDao('valar.MetaField')
|
|
28
|
+
|
|
29
|
+
meta_item = {"entity": entity, 'db': db}
|
|
30
|
+
meta: Meta = meta_dao.search(meta_item).first()
|
|
31
|
+
if meta is None:
|
|
32
|
+
meta_item.update({"name": self.dao.name, 'saved': True, 'tree': self.dao.is_tree})
|
|
33
|
+
meta = meta_dao.save_one(meta_item)
|
|
34
|
+
self.meta = meta
|
|
35
|
+
|
|
36
|
+
# load_view
|
|
37
|
+
view_item = {"code": self.code, "meta_id": meta.id}
|
|
38
|
+
view: MetaView = view_dao.search(view_item).first()
|
|
39
|
+
if view is None:
|
|
40
|
+
self.__initial_view__(view_item)
|
|
41
|
+
view = view_dao.save_one(view_item)
|
|
42
|
+
self.view = view
|
|
43
|
+
|
|
44
|
+
# load_fields
|
|
45
|
+
if view.metafield_set.count() == 0:
|
|
46
|
+
_fields = self.__initial_fields__()
|
|
47
|
+
for _field in _fields:
|
|
48
|
+
if _field['prop'] not in ['sort', 'create_time', 'modify_time', 'saved']:
|
|
49
|
+
_field.update({'view_id': view.id, "saved": True})
|
|
50
|
+
field_dao.save_one(_field)
|
|
51
|
+
|
|
52
|
+
def meta_view(self):
|
|
53
|
+
_view = self.view.json()
|
|
54
|
+
meta = self.meta.json()
|
|
55
|
+
name, entity = meta['name'], meta['entity']
|
|
56
|
+
fields = self.view.metafield_set.all().order_by('-sort')
|
|
57
|
+
_fields = {}
|
|
58
|
+
_minio = settings.MINIO_ROOT if hasattr(settings, 'MINIO_ROOT') else '/minio'
|
|
59
|
+
for field in fields:
|
|
60
|
+
_field = field.json(entity=entity, code=self.code, db='orm', minio=_minio)
|
|
61
|
+
align, tool, width, domain = _field['align'], _field['tool'], _field['column_width'], _field['domain']
|
|
62
|
+
_field['align'] = align if align else meta_field_tool_mapping.get(tool, 'left')
|
|
63
|
+
_field['column_width'] = width if width else column_width(domain, tool)
|
|
64
|
+
|
|
65
|
+
_fields[field.prop] = _field
|
|
66
|
+
|
|
67
|
+
_minio = settings.MINIO_ROOT if hasattr(settings, 'MINIO_ROOT') else '/minio'
|
|
68
|
+
_view.update({
|
|
69
|
+
'$minio': _minio,
|
|
70
|
+
'$db': 'orm',
|
|
71
|
+
'$entity': entity,
|
|
72
|
+
'$code': self.code,
|
|
73
|
+
'$meta_name': name,
|
|
74
|
+
'$isTree': self.dao.is_tree,
|
|
75
|
+
'$fields': _fields,
|
|
76
|
+
'$modes': self.dao.full_props()
|
|
77
|
+
})
|
|
78
|
+
return _view
|
|
79
|
+
|
|
80
|
+
""" 默认的view设置 """
|
|
81
|
+
|
|
82
|
+
def __initial_view__(self, view_item: dict):
|
|
83
|
+
default_view = meta_view_default_values.get(self.entity, {})
|
|
84
|
+
default_values = copy.deepcopy(default_view.get('__init__', {}))
|
|
85
|
+
code_values = copy.deepcopy(default_view.get(self.code, {}))
|
|
86
|
+
view_item.update({
|
|
87
|
+
"name": self.code.upper(),
|
|
88
|
+
"saved": True,
|
|
89
|
+
"property": {
|
|
90
|
+
"value": "id",
|
|
91
|
+
"label": "name",
|
|
92
|
+
"display": "id",
|
|
93
|
+
"sort": "sort",
|
|
94
|
+
"disabled": "disabled",
|
|
95
|
+
"isLeaf": "isLeaf",
|
|
96
|
+
"icon": "icon",
|
|
97
|
+
"children": "children",
|
|
98
|
+
"pid": "pid",
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
values = always_merger.merge(default_values, code_values)
|
|
102
|
+
view_item.update(values)
|
|
103
|
+
|
|
104
|
+
def __initial_fields__(self):
|
|
105
|
+
default_keys = meta_field_key_defaults.get(self.entity, {})
|
|
106
|
+
method, array = default_keys.get(self.code, ('omit', []))
|
|
107
|
+
|
|
108
|
+
def fun(prop):
|
|
109
|
+
return prop not in array if method == 'omit' else prop in array
|
|
110
|
+
|
|
111
|
+
props = [prop for prop in self.dao.props() if fun(prop)]
|
|
112
|
+
if method == 'pick':
|
|
113
|
+
props = [prop for prop in array if prop in props]
|
|
114
|
+
|
|
115
|
+
default_values = copy.deepcopy(meta_field_value_defaults.get(self.entity, {}))
|
|
116
|
+
init_values = default_values.get('__init__', {})
|
|
117
|
+
code_values = default_values.get(self.code, {})
|
|
118
|
+
default_fields = always_merger.merge(init_values, code_values)
|
|
119
|
+
|
|
120
|
+
fields = []
|
|
121
|
+
for prop in props:
|
|
122
|
+
field = self.dao.get_meta_field(prop)
|
|
123
|
+
field_json = field.to_dict()
|
|
124
|
+
default_field = default_fields.get(prop, {})
|
|
125
|
+
always_merger.merge(field_json, default_field)
|
|
126
|
+
fields.append(field_json)
|
|
127
|
+
fields.reverse()
|
|
128
|
+
return fields
|
valar/dao/mon_dao.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from pymongo.synchronous.collection import Collection
|
|
2
|
+
from pymongo.results import InsertOneResult
|
|
3
|
+
from pymongo.synchronous.cursor import Cursor
|
|
4
|
+
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
|
|
7
|
+
from .query import Query
|
|
8
|
+
from ..dao.abstract import AbstractDao
|
|
9
|
+
from ..dao.mon_field import MonField
|
|
10
|
+
|
|
11
|
+
domain_mapping = {
|
|
12
|
+
'ObjectId': ('BigAutoField', 'none'),
|
|
13
|
+
'int': ('CharField', 'number'),
|
|
14
|
+
'str': ('TextField', 'text'),
|
|
15
|
+
'float': ('CharField', 'number'),
|
|
16
|
+
'bool': ('BooleanField', 'boolean'),
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MonDao(AbstractDao):
|
|
21
|
+
|
|
22
|
+
def __init__(self, entity):
|
|
23
|
+
self.db = 'mon'
|
|
24
|
+
self.entity = entity
|
|
25
|
+
self.name = entity
|
|
26
|
+
self.manager: Collection = self.engine.get_mongo_collection(entity)
|
|
27
|
+
self.is_tree = False
|
|
28
|
+
fields = {}
|
|
29
|
+
for prop, domain, tool in self.__analyze_field_types__():
|
|
30
|
+
fields[prop] = MonField(entity, prop, domain, tool)
|
|
31
|
+
self.fields = fields
|
|
32
|
+
|
|
33
|
+
def __analyze_field_types__(self):
|
|
34
|
+
array = []
|
|
35
|
+
type_map = defaultdict(set)
|
|
36
|
+
cursor = self.manager.find().limit(1000)
|
|
37
|
+
for doc in cursor:
|
|
38
|
+
for key, value in doc.items():
|
|
39
|
+
type_map[key].add(type(value).__name__)
|
|
40
|
+
for prop, domains in dict(type_map).items():
|
|
41
|
+
domain, tool = domain_mapping[domains.pop()]
|
|
42
|
+
prop = 'id' if prop == '_id' else prop
|
|
43
|
+
array.append((prop, domain, tool))
|
|
44
|
+
return array
|
|
45
|
+
|
|
46
|
+
def __detach_item__(self, item):
|
|
47
|
+
_id = item.get('id')
|
|
48
|
+
if _id:
|
|
49
|
+
del item['id']
|
|
50
|
+
return self.object_id(_id), item
|
|
51
|
+
else:
|
|
52
|
+
return None, item
|
|
53
|
+
|
|
54
|
+
def save_many(self, array: list):
|
|
55
|
+
self.manager.insert_many(array)
|
|
56
|
+
|
|
57
|
+
def values(self, conditions, props):
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
def save_one(self, item, with_id=False):
|
|
61
|
+
oid, item = self.__detach_item__(item)
|
|
62
|
+
if oid:
|
|
63
|
+
self.manager.update_one({'_id': oid}, {'$set': item})
|
|
64
|
+
else:
|
|
65
|
+
bean: InsertOneResult = self.manager.insert_one(item)
|
|
66
|
+
oid = bean.inserted_id
|
|
67
|
+
self.manager.update_one({'_id': oid}, {'$set': {'sort': str(oid)}})
|
|
68
|
+
return self.manager.find_one({'_id': oid})
|
|
69
|
+
|
|
70
|
+
def delete_one(self, _id):
|
|
71
|
+
oid = self.object_id(_id)
|
|
72
|
+
flag = oid is not None
|
|
73
|
+
if flag:
|
|
74
|
+
self.manager.delete_one({'_id': oid})
|
|
75
|
+
return flag
|
|
76
|
+
|
|
77
|
+
def find_one(self, _id):
|
|
78
|
+
oid = self.object_id(_id)
|
|
79
|
+
return self.manager.find_one({'_id': oid}) if oid else None
|
|
80
|
+
|
|
81
|
+
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
82
|
+
finder, orders = Query(conditions, orders).mon()
|
|
83
|
+
skip = (page - 1) * size
|
|
84
|
+
total = self.manager.count_documents(finder)
|
|
85
|
+
cursor = self.manager.find(finder).skip(skip).sort(orders)
|
|
86
|
+
if size:
|
|
87
|
+
cursor = cursor.limit(size)
|
|
88
|
+
return cursor, total
|
|
89
|
+
|
|
90
|
+
def update(self, template, conditions):
|
|
91
|
+
flag = template is not None and len(template.keys())
|
|
92
|
+
if flag:
|
|
93
|
+
oid, item = self.__detach_item__(template)
|
|
94
|
+
finder, _ = Query(conditions).mon()
|
|
95
|
+
self.manager.update_many(finder, {'$set': item})
|
|
96
|
+
return flag
|
|
97
|
+
|
|
98
|
+
def delete(self, conditions=None) -> list:
|
|
99
|
+
finder, _ = Query(conditions).mon()
|
|
100
|
+
self.manager.delete_many(finder)
|
|
101
|
+
return []
|
|
102
|
+
|
|
103
|
+
def serialize(self, o, code=None):
|
|
104
|
+
return [__to_item__(doc) for doc in o] if isinstance(o, Cursor) else __to_item__(o)
|
|
105
|
+
|
|
106
|
+
def tree(self, root, conditions=None):
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def __to_item__(o):
|
|
111
|
+
o['id'] = str(o['_id'])
|
|
112
|
+
del o['_id']
|
|
113
|
+
return o
|