valar 1.0.17__py3-none-any.whl → 1.0.19__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/channels/__init__.py +7 -3
- valar/channels/views.py +3 -2
- valar/data/file/__init__.py +91 -0
- valar/data/migrations/0001_initial.py +56 -28
- valar/data/models.py +26 -13
- valar/data/mon/__init__.py +44 -5
- valar/data/mon/query_translator.py +91 -0
- valar/data/orm/__init__.py +57 -9
- valar/data/orm/meta.py +82 -7
- valar/data/orm/meta_frame.py +49 -0
- valar/data/orm/meta_loader.py +85 -20
- valar/data/orm/values.py +11 -2
- valar/data/query.py +14 -14
- valar/data/urls.py +18 -9
- valar/data/views.py +108 -11
- {valar-1.0.17.dist-info → valar-1.0.19.dist-info}/METADATA +5 -1
- valar-1.0.19.dist-info/RECORD +27 -0
- {valar-1.0.17.dist-info → valar-1.0.19.dist-info}/WHEEL +1 -1
- valar-1.0.17.dist-info/RECORD +0 -24
- {valar-1.0.17.dist-info → valar-1.0.19.dist-info}/licenses/LICENSE +0 -0
- {valar-1.0.17.dist-info → valar-1.0.19.dist-info}/top_level.txt +0 -0
valar/data/orm/__init__.py
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
from django.apps import apps
|
|
3
3
|
from django.core.paginator import Paginator
|
|
4
|
-
from django.db.models import Manager, QuerySet
|
|
4
|
+
from django.db.models import Manager, QuerySet, FileField
|
|
5
5
|
|
|
6
|
+
from .meta_frame import load_meta_frame
|
|
7
|
+
from ..file import minio_remove_path
|
|
6
8
|
from ..orm.detacher import detach_props, save_detached
|
|
7
9
|
from ..orm.meta_loader import load_meta, load_view, load_meta_field
|
|
8
|
-
from ..models import VModel
|
|
10
|
+
from ..models import VModel, VTree
|
|
9
11
|
from ..query import Query
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
load_meta_frame()
|
|
15
|
+
|
|
12
16
|
def load_model(entity=None):
|
|
13
17
|
mapping = {}
|
|
14
18
|
for mod in apps.get_models():
|
|
@@ -21,6 +25,9 @@ def load_model(entity=None):
|
|
|
21
25
|
mapping[key] = [mod, verbose_name]
|
|
22
26
|
return mapping.get(entity) if entity else mapping
|
|
23
27
|
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
24
31
|
class OrmDao:
|
|
25
32
|
def __init__(self, entity):
|
|
26
33
|
self.entity = entity
|
|
@@ -28,17 +35,50 @@ class OrmDao:
|
|
|
28
35
|
if param is None:
|
|
29
36
|
raise Exception('no entity named %s' % entity)
|
|
30
37
|
self.model = param[0]
|
|
38
|
+
self.isTree = issubclass(self.model, VTree)
|
|
31
39
|
self.name: str = param[1]
|
|
32
40
|
self.manager: Manager = self.model.objects
|
|
33
41
|
self.meta_fields = {}
|
|
34
42
|
self.model_fields = {}
|
|
35
43
|
for field in self.model._meta.get_fields():
|
|
36
|
-
_field = load_meta_field(field)
|
|
44
|
+
_field = load_meta_field(field, self.isTree)
|
|
37
45
|
prop = _field['prop']
|
|
38
46
|
self.model_fields[prop] = field
|
|
39
47
|
self.meta_fields[prop] = _field
|
|
40
48
|
|
|
41
49
|
|
|
50
|
+
def tree(self, query: Query, root_id = 0):
|
|
51
|
+
all_set, _ = self.find_many(Query())
|
|
52
|
+
includes, excludes = query.orm_conditions()
|
|
53
|
+
if not len(includes) + len(excludes) + root_id:
|
|
54
|
+
return all_set
|
|
55
|
+
values = all_set.values('id','pid')
|
|
56
|
+
mapping = {item['id']: item['pid'] for item in values}
|
|
57
|
+
results, _ = self.find_many(query)
|
|
58
|
+
id_set = {root_id}
|
|
59
|
+
for item in results:
|
|
60
|
+
_id = item.id
|
|
61
|
+
route = []
|
|
62
|
+
while _id is not None:
|
|
63
|
+
route.append(_id)
|
|
64
|
+
_id = mapping.get(_id)
|
|
65
|
+
if root_id in route:
|
|
66
|
+
id_set.update(route)
|
|
67
|
+
return all_set.filter(id__in=id_set).order_by('-sort')
|
|
68
|
+
|
|
69
|
+
def __check_remove_file__(self, query_set, template:dict = None):
|
|
70
|
+
props = [key for key in self.model_fields if type(self.model_fields[key]) == FileField]
|
|
71
|
+
keys = [ key for key in props if template.get(key, 1) is None] if template else props
|
|
72
|
+
if len(keys):
|
|
73
|
+
values = query_set.values(*props)
|
|
74
|
+
for row in values:
|
|
75
|
+
for path in row.values():
|
|
76
|
+
if path:
|
|
77
|
+
print(path)
|
|
78
|
+
minio_remove_path(path)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
42
82
|
def save_one(self, item):
|
|
43
83
|
_item = detach_props(item, self.meta_fields.values())
|
|
44
84
|
_id = item.get('id',0)
|
|
@@ -46,6 +86,7 @@ class OrmDao:
|
|
|
46
86
|
if len(query_set):
|
|
47
87
|
del item['id']
|
|
48
88
|
item['modify_time'] = datetime.datetime.now()
|
|
89
|
+
self.__check_remove_file__(query_set,item)
|
|
49
90
|
query_set.update(**item)
|
|
50
91
|
bean = query_set.first()
|
|
51
92
|
else:
|
|
@@ -56,18 +97,23 @@ class OrmDao:
|
|
|
56
97
|
return bean
|
|
57
98
|
|
|
58
99
|
def update_many(self, query: Query, template):
|
|
59
|
-
self.find_many(query)
|
|
100
|
+
query_set, total = self.find_many(query)
|
|
101
|
+
query_set.update(**template)
|
|
60
102
|
|
|
61
103
|
def delete_one(self, _id):
|
|
62
|
-
self.manager.filter(id=_id)
|
|
104
|
+
query_set = self.manager.filter(id=_id)
|
|
105
|
+
self.__check_remove_file__(query_set)
|
|
106
|
+
query_set.delete()
|
|
63
107
|
|
|
64
108
|
def delete_many(self, query: Query):
|
|
65
|
-
self.find_many(query)
|
|
109
|
+
query_set, total = self.find_many(query)
|
|
110
|
+
self.__check_remove_file__(query_set)
|
|
111
|
+
query_set.delete()
|
|
66
112
|
|
|
67
113
|
def find_one(self, _id):
|
|
68
114
|
return self.manager.filter(id=_id).first()
|
|
69
115
|
|
|
70
|
-
def find_many(self, query: Query, size=0, page=1)
|
|
116
|
+
def find_many(self, query: Query, size=0, page=1):
|
|
71
117
|
includes, excludes = query.orm_conditions()
|
|
72
118
|
query_set = self.manager.filter(includes).exclude(excludes).order_by(*query.orm_orders())
|
|
73
119
|
total = query_set.count()
|
|
@@ -78,10 +124,12 @@ class OrmDao:
|
|
|
78
124
|
|
|
79
125
|
|
|
80
126
|
def meta(self, code:str = 'default'):
|
|
81
|
-
omit = [ 'sort', 'create_time', 'modify_time']
|
|
127
|
+
omit = [ 'id', 'saved', 'sort', 'create_time', 'modify_time']
|
|
82
128
|
fields = [ self.meta_fields[prop] for prop in self.meta_fields if prop not in omit]
|
|
83
129
|
view = load_view(self.entity, code, self.name, fields)
|
|
84
|
-
|
|
130
|
+
_view = load_meta(view)
|
|
131
|
+
_view['isTree'] = self.isTree
|
|
132
|
+
return _view
|
|
85
133
|
|
|
86
134
|
|
|
87
135
|
|
valar/data/orm/meta.py
CHANGED
|
@@ -1,24 +1,99 @@
|
|
|
1
|
-
mf_common = ['prop','name'
|
|
1
|
+
mf_common = ['prop','name']
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
meta_props = {
|
|
4
4
|
'data.Meta': {
|
|
5
5
|
'default': ('pick', ['entity','name']),
|
|
6
6
|
},
|
|
7
7
|
'data.MetaView': {
|
|
8
8
|
'list': ('pick', ['meta_id','code','view_name']),
|
|
9
|
-
'control':('omit', ['name','meta_id', 'code', 'view_name', 'metafield'])
|
|
10
9
|
},
|
|
11
10
|
'data.MetaField': {
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
11
|
+
'add': ('pick',['prop','domain','name']),
|
|
12
|
+
'tool': ('pick',[*mf_common,'domain','tool','refer','format']),
|
|
13
|
+
'rest': ('pick',[*mf_common,'not_null','allow_edit','allow_sort','allow_search','allow_download','allow_upload','allow_update']),
|
|
14
|
+
'table': ('pick',[*mf_common,'unit','column_width','fixed','align','edit_on_table','hide_on_table','header_color','cell_color']),
|
|
15
15
|
'form': ('pick',[*mf_common,'hide_on_form','hide_on_form_insert','hide_on_form_edit','hide_on_form_branch','hide_on_form_leaf','span']),
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
meta_defaults = {
|
|
21
|
+
'data.MetaFieldDomain':{
|
|
22
|
+
"default_id":{
|
|
23
|
+
"tool":"tree"
|
|
24
|
+
},
|
|
25
|
+
"search_id":{
|
|
26
|
+
"tool":"tree"
|
|
27
|
+
},
|
|
28
|
+
"tools":{
|
|
29
|
+
"tool":"tree",
|
|
30
|
+
"refer": {
|
|
31
|
+
"display":"code"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"align":{
|
|
35
|
+
"tool":"set",
|
|
36
|
+
"format":{
|
|
37
|
+
"set": {
|
|
38
|
+
'left':'左对齐',
|
|
39
|
+
'right':'右对齐',
|
|
40
|
+
'center':'剧中对齐',
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
21
45
|
'data.MetaField':{
|
|
46
|
+
"column_width":{
|
|
47
|
+
'unit':'px'
|
|
48
|
+
},
|
|
49
|
+
"fixed":{
|
|
50
|
+
"tool":"set",
|
|
51
|
+
"format":{
|
|
52
|
+
"set": {
|
|
53
|
+
'left':'左侧固定',
|
|
54
|
+
'right':'右侧固定',
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"align":{
|
|
59
|
+
"tool":"set",
|
|
60
|
+
"format":{
|
|
61
|
+
"set": {
|
|
62
|
+
'left':'左对齐',
|
|
63
|
+
'right':'右对齐',
|
|
64
|
+
'center':'剧中对齐',
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"prop":{
|
|
69
|
+
'allow_edit': False,
|
|
70
|
+
'column_width': 120
|
|
71
|
+
},
|
|
72
|
+
"domain":{
|
|
73
|
+
'allow_edit': False,
|
|
74
|
+
'column_width': 120,
|
|
75
|
+
},
|
|
76
|
+
"tool":{
|
|
77
|
+
'column_width': 100,
|
|
78
|
+
'tool': 'tree',
|
|
79
|
+
'refer': {
|
|
80
|
+
'entity':'data.MetaFieldTool',
|
|
81
|
+
'includes': {'metafielddomain__name':'$domain'},
|
|
82
|
+
'value': 'code'
|
|
83
|
+
}
|
|
22
84
|
|
|
85
|
+
},
|
|
86
|
+
"span":{
|
|
87
|
+
'column_width': 100,
|
|
88
|
+
"format": { "min": 0, "max": 24, "step": 1, "precision": 0, "step_strictly": True }
|
|
89
|
+
},
|
|
90
|
+
"refer":{
|
|
91
|
+
'allow_edit': False,
|
|
92
|
+
'column_width': 80
|
|
93
|
+
},
|
|
94
|
+
"format":{
|
|
95
|
+
'allow_edit': False,
|
|
96
|
+
'column_width': 80
|
|
97
|
+
},
|
|
23
98
|
}
|
|
24
99
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from django.db import OperationalError
|
|
4
|
+
|
|
5
|
+
from src.valar.data.models import MetaFieldDomain, MetaFieldTool
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def load_meta_frame():
|
|
10
|
+
try:
|
|
11
|
+
MetaFieldTool.objects.all().delete()
|
|
12
|
+
MetaFieldDomain.objects.all().delete()
|
|
13
|
+
project_root = os.path.dirname(os.path.abspath(__file__))
|
|
14
|
+
file_path = os.path.join(project_root, 'meta_frame.xlsx')
|
|
15
|
+
array = pd.read_excel(file_path, sheet_name='tool').to_dict("records")
|
|
16
|
+
for row in array:
|
|
17
|
+
row['saved'] = True
|
|
18
|
+
MetaFieldTool.objects.create(**row)
|
|
19
|
+
array = pd.read_excel(file_path, sheet_name='domain').to_dict("records")
|
|
20
|
+
for row in array:
|
|
21
|
+
row['saved'] = True
|
|
22
|
+
tools = row.get('tools', '').split(';')
|
|
23
|
+
del row['tools']
|
|
24
|
+
item = MetaFieldDomain.objects.create(**row)
|
|
25
|
+
for tk in tools:
|
|
26
|
+
item.tools.add(tk)
|
|
27
|
+
except OperationalError as e:
|
|
28
|
+
print('initialization')
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def convert_meta_fields(fields, entity):
|
|
32
|
+
values = MetaFieldDomain.objects.all().values('name', 'default__code', 'align')
|
|
33
|
+
mapping = {vs['name']: {
|
|
34
|
+
"tool": vs['default__code'],
|
|
35
|
+
"align": vs['align']
|
|
36
|
+
} for vs in values}
|
|
37
|
+
array = []
|
|
38
|
+
for field in fields:
|
|
39
|
+
node = mapping[field.domain]
|
|
40
|
+
_field = field.json
|
|
41
|
+
if field.tool == 'default':
|
|
42
|
+
_field['tool'] = node['tool']
|
|
43
|
+
_field['align'] = node['align']
|
|
44
|
+
_field['entity'] = entity
|
|
45
|
+
array.append(_field)
|
|
46
|
+
return array
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
valar/data/orm/meta_loader.py
CHANGED
|
@@ -2,16 +2,17 @@ from django.db.models import (ManyToOneRel, ForeignKey, ManyToManyRel, ManyToMan
|
|
|
2
2
|
OneToOneRel, IntegerField, BooleanField, FloatField, FileField, JSONField, DateField,
|
|
3
3
|
TextField,DateTimeField, TimeField)
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from ..
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
from .meta_frame import convert_meta_fields
|
|
6
|
+
from ..orm.meta import meta_props, meta_defaults
|
|
7
|
+
from ..models import Meta, MetaView, VModel, MetaField, VTree
|
|
9
8
|
|
|
9
|
+
from deepmerge import always_merger
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def __save_model(model):
|
|
13
13
|
model.save()
|
|
14
14
|
model.sort = model.id
|
|
15
|
+
model.saved = True
|
|
15
16
|
model.save()
|
|
16
17
|
|
|
17
18
|
|
|
@@ -26,8 +27,13 @@ def load_view(entity, code, name, fields):
|
|
|
26
27
|
view = MetaView(meta=meta, code=code, view_name=code.upper())
|
|
27
28
|
__save_model(view)
|
|
28
29
|
if view.metafield_set.count() == 0:
|
|
29
|
-
t, p =
|
|
30
|
+
t, p = meta_props.get(entity, {}).get(code,('omit',[]))
|
|
30
31
|
_fields = [f for f in fields if f['prop'] not in p] if t=='omit' else [f for f in fields if f['prop'] in p]
|
|
32
|
+
defaults = meta_defaults.get(entity,{})
|
|
33
|
+
for _field in _fields:
|
|
34
|
+
prop = _field['prop']
|
|
35
|
+
_field = always_merger.merge(_field,defaults.get(prop,{}))
|
|
36
|
+
_fields.reverse()
|
|
31
37
|
for f in _fields:
|
|
32
38
|
f['view'] = view
|
|
33
39
|
field = MetaField.objects.create(**f)
|
|
@@ -37,7 +43,9 @@ def load_view(entity, code, name, fields):
|
|
|
37
43
|
def load_meta(view):
|
|
38
44
|
_view = view.full
|
|
39
45
|
_meta = _view['meta']
|
|
40
|
-
|
|
46
|
+
fields = view.metafield_set.all().order_by('-sort')
|
|
47
|
+
_fields = convert_meta_fields(fields,_meta['entity'])
|
|
48
|
+
# _fields = [f.json for f in fields]
|
|
41
49
|
clear_item(_view, 'meta_id', 'metafield', 'metafield_set', 'meta')
|
|
42
50
|
_view['meta_name'] = _meta['name']
|
|
43
51
|
_view['entity'] = _meta['entity']
|
|
@@ -53,13 +61,20 @@ def load_meta(view):
|
|
|
53
61
|
def clear_item(item, *keys):
|
|
54
62
|
del item['saved']
|
|
55
63
|
del item['sort']
|
|
56
|
-
del item['id']
|
|
57
64
|
del item['create_time']
|
|
58
65
|
del item['modify_time']
|
|
59
66
|
for key in keys:
|
|
60
67
|
del item[key]
|
|
61
68
|
|
|
62
69
|
|
|
70
|
+
def get_default_refer():
|
|
71
|
+
return {
|
|
72
|
+
"entity": None,
|
|
73
|
+
"value": "name", "label": 'name', "display": "id",
|
|
74
|
+
"strict": False, "remote": False, "multiple": False,
|
|
75
|
+
"includes": {}, "excludes": {}, "root": 0, "isTree": False
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
|
|
64
79
|
def get_refer(model, multiple = False):
|
|
65
80
|
module, name = model.__module__, model.__name__
|
|
@@ -68,34 +83,72 @@ def get_refer(model, multiple = False):
|
|
|
68
83
|
"entity": entity,
|
|
69
84
|
"value": "id", "label": 'name', "display": "id",
|
|
70
85
|
"strict": False, "remote": False, "multiple": multiple,
|
|
71
|
-
"includes": {}, "excludes": {}, "root": 0,
|
|
86
|
+
"includes": {}, "excludes": {}, "root": 0, "isTree": issubclass(model, VTree)
|
|
72
87
|
}
|
|
73
88
|
|
|
74
89
|
def get_align(clazz):
|
|
75
|
-
if clazz in [FloatField, IntegerField
|
|
90
|
+
if clazz in [FloatField, IntegerField]: #, ManyToManyRel, ManyToManyField, ManyToOneRel
|
|
76
91
|
return 'right'
|
|
77
92
|
elif clazz in [BooleanField,FileField,JSONField,DateField,DateTimeField,TimeField]:
|
|
78
93
|
return 'center'
|
|
79
94
|
return 'left'
|
|
80
95
|
|
|
96
|
+
def get_default_format():
|
|
97
|
+
return {
|
|
98
|
+
# 文本
|
|
99
|
+
"maxlength": 0,
|
|
100
|
+
"type": 'text',
|
|
101
|
+
|
|
102
|
+
# 数值
|
|
103
|
+
"min": None,
|
|
104
|
+
"max": None,
|
|
105
|
+
"step": 1,
|
|
106
|
+
"precision": None,
|
|
107
|
+
"step_strictly": False,
|
|
108
|
+
|
|
109
|
+
# 日期
|
|
110
|
+
"frequency": "date",
|
|
111
|
+
|
|
112
|
+
# 文件
|
|
113
|
+
"maximum": 5,
|
|
114
|
+
"width": 800,
|
|
115
|
+
"height": 0,
|
|
116
|
+
"accept": [],
|
|
117
|
+
"file_name_field":None,
|
|
118
|
+
"locked": False,
|
|
119
|
+
|
|
120
|
+
#集合
|
|
121
|
+
"set": {}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
81
126
|
def get_format(field):
|
|
82
127
|
clazz = type(field)
|
|
128
|
+
_format = get_default_format()
|
|
83
129
|
if clazz == CharField:
|
|
84
|
-
|
|
130
|
+
_format['maxlength'] = field.max_length
|
|
85
131
|
if clazz == TextField:
|
|
86
|
-
|
|
87
|
-
elif clazz ==
|
|
88
|
-
|
|
132
|
+
_format['type'] = "textarea"
|
|
133
|
+
elif clazz == DateTimeField:
|
|
134
|
+
_format['frequency'] = "datetime"
|
|
89
135
|
elif clazz == IntegerField:
|
|
90
|
-
|
|
136
|
+
_format['precision'] = 0
|
|
137
|
+
_format['step_strictly'] = True
|
|
91
138
|
elif clazz == FileField:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return {}
|
|
139
|
+
pass
|
|
140
|
+
return _format
|
|
95
141
|
|
|
142
|
+
def get_field_column_width(field,clazz):
|
|
143
|
+
if clazz in [BooleanField, FileField, JSONField]:
|
|
144
|
+
return 100
|
|
145
|
+
elif clazz in [ DateField, DateTimeField, TimeField]:
|
|
146
|
+
return 120
|
|
147
|
+
return 0
|
|
96
148
|
|
|
97
149
|
|
|
98
|
-
|
|
150
|
+
|
|
151
|
+
def load_meta_field(field, isTree):
|
|
99
152
|
clazz = type(field)
|
|
100
153
|
if clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel]:
|
|
101
154
|
prop = field.name
|
|
@@ -119,11 +172,12 @@ def load_meta_field(field):
|
|
|
119
172
|
prop = field.name
|
|
120
173
|
domain = field.get_internal_type()
|
|
121
174
|
label = field.verbose_name
|
|
122
|
-
refer =
|
|
175
|
+
refer = get_default_refer()
|
|
123
176
|
not_null = not field.null
|
|
124
177
|
align = get_align(clazz)
|
|
125
178
|
_format = get_format(field)
|
|
126
|
-
|
|
179
|
+
column_width = get_field_column_width(field,clazz)
|
|
180
|
+
_field = {
|
|
127
181
|
"prop": prop,
|
|
128
182
|
"label":label,
|
|
129
183
|
"name":label,
|
|
@@ -132,4 +186,15 @@ def load_meta_field(field):
|
|
|
132
186
|
"format":_format,
|
|
133
187
|
"not_null":not_null,
|
|
134
188
|
"align":align,
|
|
189
|
+
"column_width":column_width
|
|
135
190
|
}
|
|
191
|
+
|
|
192
|
+
if isTree:
|
|
193
|
+
if prop in ['pid','isLeaf']:
|
|
194
|
+
_field['hide_on_table'] = True
|
|
195
|
+
_field['hide_on_form'] = True
|
|
196
|
+
_field['hide_on_form_branch'] = True
|
|
197
|
+
_field['hide_on_form_leaf'] = True
|
|
198
|
+
elif prop in ['icon']:
|
|
199
|
+
_field['tool'] = 'icon'
|
|
200
|
+
return _field
|
valar/data/orm/values.py
CHANGED
|
@@ -43,6 +43,13 @@ def get_props(model:VModel, code):
|
|
|
43
43
|
return simple_props, referred_fields, date_props
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
def __get_ref_keys__(related_model):
|
|
47
|
+
"""新增功能"""
|
|
48
|
+
return [f.name for f in related_model._meta.get_fields()
|
|
49
|
+
if type(f) not in [ManyToManyField, ManyToOneRel, ManyToManyRel, ForeignKey, OneToOneField, OneToOneRel]
|
|
50
|
+
and f.name not in ['create_time', 'modify_time', 'saved', 'sort']
|
|
51
|
+
]
|
|
52
|
+
|
|
46
53
|
def to_dict(query_set: QuerySet, code=None):
|
|
47
54
|
model = query_set.model
|
|
48
55
|
simple_props, referred_fields, date_props = get_props(model, code)
|
|
@@ -62,8 +69,9 @@ def to_dict(query_set: QuerySet, code=None):
|
|
|
62
69
|
keys = {'id', value, display, label}
|
|
63
70
|
if clazz in [ForeignKey, OneToOneField, OneToOneRel]:
|
|
64
71
|
related_model = field.related_model
|
|
72
|
+
__keys = __get_ref_keys__(related_model)
|
|
65
73
|
related_pks = set([row.get(prop) for row in results if row.get(prop)])
|
|
66
|
-
related_items = related_model.objects.filter(id__in=related_pks).values(*
|
|
74
|
+
related_items = related_model.objects.filter(id__in=related_pks).values(*__keys)
|
|
67
75
|
mapping = {item['id']: item for item in related_items}
|
|
68
76
|
for row in results:
|
|
69
77
|
value = row.get(prop)
|
|
@@ -82,7 +90,8 @@ def to_dict(query_set: QuerySet, code=None):
|
|
|
82
90
|
array.append(_pk)
|
|
83
91
|
row_mapping[_id] = array
|
|
84
92
|
related_model = field.related_model
|
|
85
|
-
|
|
93
|
+
__keys = __get_ref_keys__(related_model)
|
|
94
|
+
related_items = related_model.objects.filter(id__in=_pks).values(*__keys)
|
|
86
95
|
mapping = {item['id']: item for item in related_items}
|
|
87
96
|
for row in results:
|
|
88
97
|
_id = row.get('id')
|
valar/data/query.py
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
from functools import reduce
|
|
2
|
-
|
|
3
|
-
|
|
4
2
|
from django.db.models import Q
|
|
5
3
|
|
|
6
4
|
|
|
@@ -17,15 +15,18 @@ class Query:
|
|
|
17
15
|
def __init__(self, body=None):
|
|
18
16
|
if body is None:
|
|
19
17
|
body = {}
|
|
20
|
-
self.template = body.get('template',{})
|
|
21
|
-
self.condition = Condition(body.get('condition',{}))
|
|
22
|
-
self.search = [
|
|
23
|
-
self.orders = body.get('orders',{})
|
|
18
|
+
self.template = body.get('template', {})
|
|
19
|
+
self.condition = Condition(body.get('condition', {}))
|
|
20
|
+
self.search = [Condition(condition) for condition in body.get('search', [])]
|
|
21
|
+
self.orders = body.get('orders', {})
|
|
22
|
+
self.finder = body.get('finder', {})
|
|
23
|
+
self.page = body.get('page',1)
|
|
24
|
+
self.size = body.get('size', 0)
|
|
24
25
|
|
|
25
26
|
def orm_orders(self):
|
|
26
27
|
array = []
|
|
27
|
-
for key in self.orders
|
|
28
|
-
value = self.orders
|
|
28
|
+
for key in self.orders:
|
|
29
|
+
value = self.orders.get(key)
|
|
29
30
|
prefix = '-' if value == -1 else ''
|
|
30
31
|
array.append(f'{prefix}{key}')
|
|
31
32
|
return array
|
|
@@ -33,16 +34,15 @@ class Query:
|
|
|
33
34
|
def orm_conditions(self):
|
|
34
35
|
includes, excludes = self.condition.includes, self.condition.excludes
|
|
35
36
|
if len(self.search):
|
|
36
|
-
inc = [
|
|
37
|
-
exc = [
|
|
38
|
-
def fun(x, y):return x | y
|
|
37
|
+
inc = [Q(**{**includes, **sea.includes}) for sea in self.search]
|
|
38
|
+
exc = [Q(**{**excludes, **sea.excludes}) for sea in self.search]
|
|
39
|
+
def fun(x, y): return x | y
|
|
39
40
|
return [reduce(fun, inc), reduce(fun, exc)]
|
|
40
41
|
else:
|
|
41
42
|
return [Q(**self.condition.includes), Q(**self.condition.excludes)]
|
|
42
43
|
|
|
43
44
|
def mon_conditions(self):
|
|
44
|
-
|
|
45
|
-
return
|
|
46
|
-
|
|
45
|
+
from .mon.query_translator import MongoQueryTranslator
|
|
46
|
+
return MongoQueryTranslator.translate_query(self)
|
|
47
47
|
|
|
48
48
|
# def _mon_conditions(self):
|
valar/data/urls.py
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
from django.urls import path
|
|
1
|
+
from django.urls import path, include
|
|
2
2
|
|
|
3
3
|
from ..data import views
|
|
4
4
|
|
|
5
5
|
urlpatterns = [
|
|
6
|
-
path('save_one', views.save_one),
|
|
7
|
-
path('save_many', views.save_many),
|
|
8
|
-
path('
|
|
9
|
-
|
|
10
|
-
path('
|
|
11
|
-
path('
|
|
12
|
-
path('
|
|
13
|
-
path('
|
|
6
|
+
path('<str:db>/<str:entity>/save_one', views.save_one),
|
|
7
|
+
path('<str:db>/<str:entity>/save_many', views.save_many),
|
|
8
|
+
path('<str:db>/<str:entity>/save_file', views.save_file),
|
|
9
|
+
|
|
10
|
+
path('<str:db>/<str:entity>/update_many', views.update_many),
|
|
11
|
+
path('<str:db>/<str:entity>/delete_one', views.delete_one),
|
|
12
|
+
path('<str:db>/<str:entity>/delete_many', views.delete_many),
|
|
13
|
+
path('<str:db>/<str:entity>/find_one', views.find_one),
|
|
14
|
+
path('<str:db>/<str:entity>/find_many', views.find_many),
|
|
15
|
+
path('find_file/<str:bucket_name>/<str:object_name>', views.find_file),
|
|
16
|
+
path('<str:db>/<str:entity>/tree', views.tree),
|
|
14
17
|
|
|
18
|
+
# path('data/<str:db>/<str:entity>/', include('src.valar.data.urls')),
|
|
19
|
+
|
|
20
|
+
path('add_fields', views.add_fields),
|
|
21
|
+
path('fields', views.fields),
|
|
22
|
+
path('meta', views.meta),
|
|
23
|
+
path('metas', views.metas),
|
|
15
24
|
]
|