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
valar/models/core.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
1
3
|
from django.apps import AppConfig
|
|
2
4
|
from django.db import models
|
|
3
5
|
from django.db.models import ManyToOneRel, OneToOneRel, ManyToManyRel, ManyToManyField, UUIDField, FileField, \
|
|
4
|
-
ForeignKey, OneToOneField, DateField, TimeField, DateTimeField, BigAutoField
|
|
6
|
+
ForeignKey, OneToOneField, DateField, TimeField, DateTimeField, BigAutoField, JSONField
|
|
5
7
|
from django.db.models.options import Options
|
|
6
8
|
|
|
7
9
|
|
|
@@ -11,7 +13,8 @@ class VModel(models.Model):
|
|
|
11
13
|
name = models.CharField(max_length=50, null=True)
|
|
12
14
|
create_time = models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')
|
|
13
15
|
modify_time = models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')
|
|
14
|
-
|
|
16
|
+
disabled = models.BooleanField(default=False, verbose_name='禁用')
|
|
17
|
+
saved = models.BooleanField(default=False, verbose_name='已保存')
|
|
15
18
|
|
|
16
19
|
class Meta:
|
|
17
20
|
abstract = True
|
|
@@ -19,7 +22,7 @@ class VModel(models.Model):
|
|
|
19
22
|
def __str__(self):
|
|
20
23
|
return str(self.full())
|
|
21
24
|
|
|
22
|
-
def get_meta(self)->Options:
|
|
25
|
+
def get_meta(self) -> Options:
|
|
23
26
|
return getattr(self, '_meta')
|
|
24
27
|
|
|
25
28
|
def get_entity(self):
|
|
@@ -47,9 +50,9 @@ class VModel(models.Model):
|
|
|
47
50
|
elif domain in [FileField]:
|
|
48
51
|
value = value.name
|
|
49
52
|
elif domain in [BigAutoField]:
|
|
50
|
-
value =
|
|
53
|
+
value = value
|
|
51
54
|
data[prop] = value
|
|
52
|
-
data.update({f'${k}': v for k,v in kwargs.items()})
|
|
55
|
+
data.update({f'${k}': v for k, v in kwargs.items()})
|
|
53
56
|
return data
|
|
54
57
|
|
|
55
58
|
def full(self):
|
|
@@ -59,24 +62,27 @@ class VModel(models.Model):
|
|
|
59
62
|
for field in fields:
|
|
60
63
|
prop = field.name
|
|
61
64
|
domain = type(field)
|
|
62
|
-
if domain in [ForeignKey,OneToOneField]:
|
|
65
|
+
if domain in [ForeignKey, OneToOneField]:
|
|
63
66
|
bean: VModel = getattr(self, prop)
|
|
64
67
|
data[prop] = bean.json() if bean else None
|
|
65
68
|
elif domain == OneToOneRel:
|
|
66
69
|
print('OneToOneRel')
|
|
67
70
|
pass
|
|
68
|
-
elif domain
|
|
69
|
-
|
|
71
|
+
elif domain == JSONField:
|
|
72
|
+
data[prop] = json.loads(data[prop]) if type(data[prop]) is str else data[prop]
|
|
73
|
+
elif domain in [ManyToManyField, ManyToManyRel, ManyToOneRel]:
|
|
74
|
+
accessor = prop if domain == ManyToManyField else field.get_accessor_name()
|
|
70
75
|
_set = getattr(self, accessor).all().order_by('-sort')
|
|
71
76
|
data[prop] = [item.id for item in _set]
|
|
72
77
|
data[f'{prop}_set'] = [item.json() for item in _set]
|
|
78
|
+
|
|
73
79
|
return data
|
|
74
80
|
|
|
75
81
|
|
|
76
82
|
class VTree(VModel):
|
|
77
83
|
pid = models.IntegerField(null=False, default=0, verbose_name='父节点')
|
|
78
|
-
isLeaf = models.BooleanField(
|
|
84
|
+
isLeaf = models.BooleanField(default=False, verbose_name='叶子节点')
|
|
79
85
|
icon = models.CharField(max_length=255, null=True, verbose_name='图标')
|
|
86
|
+
|
|
80
87
|
class Meta:
|
|
81
88
|
abstract = True
|
|
82
|
-
|
valar/models/frame.py
CHANGED
|
@@ -5,9 +5,12 @@ from .core import VModel, VTree
|
|
|
5
5
|
class MetaFieldTool(VTree):
|
|
6
6
|
name = models.CharField(max_length=255, null=True, verbose_name='名称')
|
|
7
7
|
code = models.CharField(max_length=100, unique=True, null=True, verbose_name='代码') #
|
|
8
|
+
align = models.CharField(max_length=10, null=True, verbose_name='对齐方式')
|
|
8
9
|
|
|
9
10
|
class Meta:
|
|
10
11
|
verbose_name = '元数据字段工具'
|
|
12
|
+
|
|
13
|
+
|
|
11
14
|
#
|
|
12
15
|
#
|
|
13
16
|
|
|
@@ -19,12 +22,6 @@ class MetaFieldDomain(VModel):
|
|
|
19
22
|
on_delete=models.SET_NULL,
|
|
20
23
|
related_name='+',
|
|
21
24
|
verbose_name='默认工具')
|
|
22
|
-
|
|
23
|
-
to=MetaFieldTool, null=True,
|
|
24
|
-
on_delete=models.SET_NULL,
|
|
25
|
-
related_name='+',
|
|
26
|
-
verbose_name='搜索工具')
|
|
27
|
-
align = models.CharField(max_length=10, null=True, verbose_name='对齐方式')
|
|
25
|
+
|
|
28
26
|
class Meta:
|
|
29
27
|
verbose_name = '元数据字段类型'
|
|
30
|
-
|
valar/models/meta.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
from django.db import models
|
|
2
|
-
from .core import VModel
|
|
2
|
+
from .core import VModel, VTree
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class Meta(VModel):
|
|
6
6
|
db = models.CharField(max_length=100, verbose_name='数据库', null=True)
|
|
7
7
|
entity = models.CharField(max_length=100, verbose_name='数据源', null=True)
|
|
8
8
|
name = models.CharField(max_length=50, verbose_name='实体别名', null=True)
|
|
9
|
+
tree = models.BooleanField(default=False, verbose_name='是否树形')
|
|
9
10
|
|
|
10
11
|
class Meta:
|
|
11
12
|
verbose_name = '数据实体'
|
|
@@ -14,22 +15,27 @@ class Meta(VModel):
|
|
|
14
15
|
|
|
15
16
|
class MetaView(VModel):
|
|
16
17
|
meta = models.ForeignKey('Meta', on_delete=models.CASCADE, verbose_name='元数据')
|
|
18
|
+
property = models.JSONField(default=dict, verbose_name='属性')
|
|
17
19
|
|
|
18
20
|
code = models.CharField(max_length=50, verbose_name='类视图', default='default ')
|
|
19
21
|
name = models.CharField(max_length=50, verbose_name='视图名称', null=True)
|
|
22
|
+
lock = models.BooleanField(default=False, verbose_name='锁定元数据')
|
|
23
|
+
enable = models.BooleanField(default=True, verbose_name='是否启用')
|
|
20
24
|
|
|
21
|
-
form_width = models.IntegerField(
|
|
22
|
-
form_height = models.IntegerField(
|
|
23
|
-
table_width = models.IntegerField(
|
|
24
|
-
table_height = models.IntegerField(
|
|
25
|
+
form_width = models.IntegerField(null=True, verbose_name='表单宽度')
|
|
26
|
+
form_height = models.IntegerField(null=True, verbose_name='表单高度')
|
|
27
|
+
table_width = models.IntegerField(null=True, verbose_name='表格宽度')
|
|
28
|
+
table_height = models.IntegerField(null=True, verbose_name='表格高度')
|
|
25
29
|
|
|
26
|
-
enable = models.BooleanField(default=True, verbose_name='是否启用')
|
|
27
|
-
show_header = models.BooleanField(default=True, verbose_name='展示头部')
|
|
28
30
|
allow_search = models.BooleanField(default=True, verbose_name='检索功能')
|
|
29
|
-
allow_sort = models.BooleanField(default=True, verbose_name='移动功能')
|
|
30
31
|
allow_order = models.BooleanField(default=True, verbose_name='排序功能')
|
|
31
32
|
allow_insert = models.BooleanField(default=True, verbose_name='新增功能')
|
|
33
|
+
|
|
32
34
|
allow_edit = models.BooleanField(default=True, verbose_name='编辑功能')
|
|
35
|
+
allow_edit_on_form = models.BooleanField(default=True, verbose_name='表单编辑')
|
|
36
|
+
allow_edit_on_cell = models.BooleanField(default=True, verbose_name='表内编辑')
|
|
37
|
+
allow_edit_on_sort = models.BooleanField(default=True, verbose_name='移动功能')
|
|
38
|
+
|
|
33
39
|
allow_remove = models.BooleanField(default=True, verbose_name='删除功能')
|
|
34
40
|
allow_download = models.BooleanField(default=True, verbose_name='下载功能')
|
|
35
41
|
allow_upload = models.BooleanField(default=True, verbose_name='上传功能')
|
|
@@ -52,20 +58,20 @@ class MetaField(VModel):
|
|
|
52
58
|
refer = models.JSONField(default=dict, verbose_name='索引') #
|
|
53
59
|
format = models.JSONField(default=dict, verbose_name='格式') #
|
|
54
60
|
|
|
55
|
-
|
|
56
61
|
"""rest"""
|
|
57
|
-
|
|
62
|
+
disabled = models.BooleanField(default=False, verbose_name='禁用') #
|
|
63
|
+
not_null = models.BooleanField(default=False, verbose_name='不为空') #
|
|
58
64
|
allow_edit = models.BooleanField(default=True, verbose_name='可编辑')
|
|
59
65
|
allow_order = models.BooleanField(default=True, verbose_name='可排序')
|
|
60
66
|
allow_search = models.BooleanField(default=True, verbose_name='可搜索')
|
|
61
67
|
allow_download = models.BooleanField(default=True, verbose_name='可下载')
|
|
62
|
-
allow_upload = models.BooleanField(default=
|
|
63
|
-
allow_update = models.BooleanField(default=
|
|
68
|
+
allow_upload = models.BooleanField(default=True, verbose_name='可上传')
|
|
69
|
+
allow_update = models.BooleanField(default=True, verbose_name='可更新')
|
|
64
70
|
|
|
65
71
|
"""table"""
|
|
66
72
|
unit = models.CharField(max_length=55, verbose_name='单位符', null=True)
|
|
67
73
|
column_width = models.FloatField(default=0, verbose_name='表头宽度')
|
|
68
|
-
align = models.CharField(max_length=55,
|
|
74
|
+
align = models.CharField(max_length=55, null=True, verbose_name='对齐方式') #
|
|
69
75
|
fixed = models.CharField(max_length=100, verbose_name='固定位置', null=True)
|
|
70
76
|
header_color = models.CharField(max_length=55, verbose_name='表头颜色', null=True)
|
|
71
77
|
cell_color = models.CharField(max_length=55, verbose_name='单元颜色', null=True)
|
|
@@ -80,8 +86,5 @@ class MetaField(VModel):
|
|
|
80
86
|
hide_on_form_branch = models.BooleanField(default=False, verbose_name='分支隐藏')
|
|
81
87
|
hide_on_form_leaf = models.BooleanField(default=False, verbose_name='叶子隐藏')
|
|
82
88
|
|
|
83
|
-
|
|
84
89
|
class Meta:
|
|
85
90
|
verbose_name = '视图字段'
|
|
86
|
-
|
|
87
|
-
|
valar/urls.py
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
from django.urls import path
|
|
2
2
|
|
|
3
3
|
from .channels.views import handel_channel
|
|
4
|
+
from .views import rest, meta, file
|
|
4
5
|
|
|
5
6
|
urlpatterns = [
|
|
6
7
|
path('socket/<str:handler>', handel_channel),
|
|
8
|
+
path('batch', rest.batch),
|
|
9
|
+
path('<str:db>/<str:entity>/save_one', rest.save_one),
|
|
10
|
+
path('<str:db>/<str:entity>/delete_one', rest.delete_one),
|
|
11
|
+
path('<str:db>/<str:entity>/find_one', rest.find_one),
|
|
12
|
+
path('<str:db>/<str:entity>/find', rest.find),
|
|
13
|
+
path('<str:db>/<str:entity>/update', rest.update),
|
|
14
|
+
path('<str:db>/<str:entity>/search', rest.search),
|
|
15
|
+
path('<str:db>/<str:entity>/values', rest.values),
|
|
16
|
+
# path('<str:db>/<str:entity>/tree', rest.tree),
|
|
17
|
+
|
|
18
|
+
path('<str:db>/<str:entity>/meta_view', meta.meta_view),
|
|
19
|
+
path('metas', meta.metas),
|
|
20
|
+
path('add_fields', meta.add_fields),
|
|
21
|
+
path('load_customs', meta.load_customs),
|
|
22
|
+
path('get_fields', meta.get_fields),
|
|
23
|
+
path('save_custom', meta.save_custom),
|
|
24
|
+
path('upload_mapping', meta.upload_mapping),
|
|
25
|
+
|
|
26
|
+
path('<str:db>/<str:entity>/save_file', file.save_file),
|
|
27
|
+
path('<str:db>/<str:entity>/remove_file', file.remove_file),
|
|
28
|
+
|
|
7
29
|
]
|
valar/views/file.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from minio import Minio
|
|
4
|
+
|
|
5
|
+
from ..classes.valar_response import ValarResponse
|
|
6
|
+
from django.core.files.uploadedfile import InMemoryUploadedFile
|
|
7
|
+
from django.http import QueryDict
|
|
8
|
+
|
|
9
|
+
from ..dao import Dao, OrmDao
|
|
10
|
+
from ..dao.engine import ValarEngine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def save_file(request, db, entity):
|
|
14
|
+
params: QueryDict = request.POST.dict()
|
|
15
|
+
_id, prop, field = (params.get(key) for key in ['id', 'prop', 'field'])
|
|
16
|
+
file: InMemoryUploadedFile = request.FILES['file']
|
|
17
|
+
dao = Dao(entity, db)
|
|
18
|
+
engine = ValarEngine().get_minio_bucket(entity)
|
|
19
|
+
item = dao.find_one(_id)
|
|
20
|
+
if engine is None or item is None:
|
|
21
|
+
return ValarResponse(False)
|
|
22
|
+
old_value = getattr(item, prop)
|
|
23
|
+
if old_value:
|
|
24
|
+
engine.remove(old_value.name)
|
|
25
|
+
object_name = engine.get_object_name(_id, prop, file.name)
|
|
26
|
+
path = engine.upload(object_name, file.read())
|
|
27
|
+
setattr(item, prop, path)
|
|
28
|
+
if field:
|
|
29
|
+
setattr(item, field, file.name)
|
|
30
|
+
item.save()
|
|
31
|
+
return ValarResponse(path)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def remove_file(request, db, entity):
|
|
35
|
+
body = json.loads(request.body)
|
|
36
|
+
_id, prop, field = (body.get(key) for key in ['id', 'prop', 'field'])
|
|
37
|
+
dao = Dao(entity, db)
|
|
38
|
+
item = dao.find_one(_id)
|
|
39
|
+
engine = ValarEngine().get_minio_bucket(entity)
|
|
40
|
+
if engine is None or item is None:
|
|
41
|
+
return ValarResponse(False)
|
|
42
|
+
old_value = getattr(item, prop)
|
|
43
|
+
if old_value:
|
|
44
|
+
engine.remove(old_value.name)
|
|
45
|
+
setattr(item, prop, None)
|
|
46
|
+
if field:
|
|
47
|
+
setattr(item, field, None)
|
|
48
|
+
item.save()
|
|
49
|
+
return ValarResponse(True)
|
valar/views/handler.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from ..channels.counter import Counter
|
|
2
|
+
from ..channels.sender import ValarChannelSender
|
|
3
|
+
from ..dao import Dao
|
|
4
|
+
from ..dao.engine import ValarEngine
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def batch_handler(sender: ValarChannelSender):
|
|
8
|
+
data = sender.data
|
|
9
|
+
entity, db, method = data.get("entity"), data.get("db"), data.get("method")
|
|
10
|
+
dao = Dao(entity, db)
|
|
11
|
+
body = {"method": method}
|
|
12
|
+
if method == 'save_many':
|
|
13
|
+
array = data.get("array", [])
|
|
14
|
+
counter = Counter(array)
|
|
15
|
+
keys = []
|
|
16
|
+
for item in array:
|
|
17
|
+
item.update({'saved': True})
|
|
18
|
+
bean = dao.save_one(item)
|
|
19
|
+
keys.append(bean.id)
|
|
20
|
+
payload = counter.tick()
|
|
21
|
+
sender.load(payload)
|
|
22
|
+
body.update({'keys': keys})
|
|
23
|
+
sender.done(body)
|
|
24
|
+
elif method == 'delete_many':
|
|
25
|
+
conditions = data.get("conditions", [])
|
|
26
|
+
paths = dao.delete(conditions)
|
|
27
|
+
counter = Counter(len(paths))
|
|
28
|
+
minio = ValarEngine().get_minio_bucket(entity)
|
|
29
|
+
for path in paths:
|
|
30
|
+
minio.remove(path)
|
|
31
|
+
payload = counter.tick()
|
|
32
|
+
sender.load(payload)
|
|
33
|
+
sender.done(body)
|
valar/views/meta.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from django.db.models import Count, Q
|
|
4
|
+
|
|
5
|
+
from ..classes.valar_response import ValarResponse
|
|
6
|
+
from ..dao import Dao
|
|
7
|
+
from ..dao.abstract import AbstractField
|
|
8
|
+
|
|
9
|
+
from ..dao.meta import ValarMeta
|
|
10
|
+
from ..models.meta import MetaView, Meta, MetaField
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def upload_mapping(request):
|
|
14
|
+
body = json.loads(request.body)
|
|
15
|
+
db = body.get('db')
|
|
16
|
+
entity = body.get('entity')
|
|
17
|
+
code = body.get('code')
|
|
18
|
+
fields = MetaField.objects.filter(
|
|
19
|
+
view__meta__db=db,
|
|
20
|
+
view__meta__entity=entity,
|
|
21
|
+
view__code=code,
|
|
22
|
+
domain__in=['ManyToManyField', 'ManyToManyRel', 'ManyToOneRel', 'OneToOneField', 'OneToOneRel', 'ForeignKey']
|
|
23
|
+
).filter(Q(allow_upload=True) | Q(allow_update=True))
|
|
24
|
+
mapping = {}
|
|
25
|
+
for field in fields:
|
|
26
|
+
prop = field.prop
|
|
27
|
+
refer = field.refer
|
|
28
|
+
db = refer['db']
|
|
29
|
+
entity = refer['entity']
|
|
30
|
+
value = refer['value']
|
|
31
|
+
label = refer['label']
|
|
32
|
+
includes = {prop: refer['includes'][prop] for prop in refer['includes'] if not prop.startswith('$')}
|
|
33
|
+
excludes = {prop: refer['excludes'][prop] for prop in refer['excludes'] if not prop.startswith('$')}
|
|
34
|
+
values = Dao(entity, db).manager.filter(**includes).exclude(**excludes).values(*[value, label])
|
|
35
|
+
mapping[prop] = {
|
|
36
|
+
row[value]: row[label]
|
|
37
|
+
for row in values if row[value]
|
|
38
|
+
}
|
|
39
|
+
return ValarResponse(mapping)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def meta_view(request, db, entity):
|
|
43
|
+
body = json.loads(request.body)
|
|
44
|
+
code = body.get('code')
|
|
45
|
+
meta = ValarMeta(db, entity, code)
|
|
46
|
+
_view = meta.meta_view()
|
|
47
|
+
return ValarResponse(_view)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def load_customs(request):
|
|
51
|
+
body = json.loads(request.body)
|
|
52
|
+
db = body.get('db')
|
|
53
|
+
entity = body.get('entity')
|
|
54
|
+
code = body.get('code')
|
|
55
|
+
ps = MetaField.objects.filter(
|
|
56
|
+
view__code=code, view__meta__db=db, view__meta__entity=entity,
|
|
57
|
+
domain='Custom').values('prop')
|
|
58
|
+
current = [p.get('prop') for p in ps]
|
|
59
|
+
return ValarResponse(current)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_fields(request):
|
|
63
|
+
body = json.loads(request.body)
|
|
64
|
+
db = body.get('db')
|
|
65
|
+
entity = body.get('entity')
|
|
66
|
+
route = body.get('route')
|
|
67
|
+
dao = Dao(entity, db)
|
|
68
|
+
array = []
|
|
69
|
+
for prop in dao.fields:
|
|
70
|
+
field: AbstractField = dao.fields.get(prop)
|
|
71
|
+
if field is None:
|
|
72
|
+
continue
|
|
73
|
+
domain: str = field.domain
|
|
74
|
+
if domain is None or domain.startswith('ManyTo'):
|
|
75
|
+
continue
|
|
76
|
+
elif domain in ['ForeignKey', 'OneToOneRel', 'OneToOneField']:
|
|
77
|
+
refer = field.refer or {}
|
|
78
|
+
_db = refer.get('db')
|
|
79
|
+
_entity = refer.get('entity')
|
|
80
|
+
_dao = Dao(_entity, _db)
|
|
81
|
+
if f'{_db}.{_entity}' in route:
|
|
82
|
+
continue
|
|
83
|
+
array.append({
|
|
84
|
+
'label': field.label,
|
|
85
|
+
'value': field.prop.replace('_id', ''),
|
|
86
|
+
'isLeaf': False,
|
|
87
|
+
'db': _db,
|
|
88
|
+
'entity': _entity,
|
|
89
|
+
})
|
|
90
|
+
elif len(route) > 1:
|
|
91
|
+
array.append({
|
|
92
|
+
'label': field.label,
|
|
93
|
+
'value': field.prop,
|
|
94
|
+
'isLeaf': True,
|
|
95
|
+
})
|
|
96
|
+
return ValarResponse(array)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def save_custom(request):
|
|
100
|
+
return ValarResponse(True)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def add_fields(request):
|
|
104
|
+
body = json.loads(request.body)
|
|
105
|
+
view_id = body.get('view_id')
|
|
106
|
+
props = body.get('props')
|
|
107
|
+
view_dao = Dao('valar.MetaView')
|
|
108
|
+
field_dao = Dao('valar.MetaField')
|
|
109
|
+
view: MetaView = view_dao.find_one(view_id)
|
|
110
|
+
entity = view.meta.entity
|
|
111
|
+
db = view.meta.db
|
|
112
|
+
dao = Dao(entity, db)
|
|
113
|
+
for prop in props:
|
|
114
|
+
field: AbstractField = dao.fields.get(prop)
|
|
115
|
+
if field:
|
|
116
|
+
_field = field.to_dict()
|
|
117
|
+
_field['view_id'] = view_id
|
|
118
|
+
field_dao.save_one(_field)
|
|
119
|
+
|
|
120
|
+
return ValarResponse(True)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def metas(request):
|
|
124
|
+
values = Meta.objects.all().values('db', 'entity', 'name', 'tree', 'metaview__name')
|
|
125
|
+
mapping = {'orm': {'valar': []}, 'mon': []}
|
|
126
|
+
for row in values:
|
|
127
|
+
db = row['db']
|
|
128
|
+
label = row['name']
|
|
129
|
+
value = row['entity']
|
|
130
|
+
tree = row['tree']
|
|
131
|
+
icon = 'folder-tree' if tree else 'table'
|
|
132
|
+
row.update({'label': label, 'value': value, 'icon': icon})
|
|
133
|
+
if db == 'orm':
|
|
134
|
+
app, _ = value.split('.')
|
|
135
|
+
array = mapping['orm'].get(app, [])
|
|
136
|
+
array.append(row)
|
|
137
|
+
mapping['orm'][app] = array
|
|
138
|
+
elif db == 'mon':
|
|
139
|
+
mapping['mon'].append(row)
|
|
140
|
+
|
|
141
|
+
mon = {'label': 'MongoDB', 'value': 'mon', 'icon': 'boxes', 'children': mapping['mon']}
|
|
142
|
+
orm = {
|
|
143
|
+
'label': 'SQL', 'value': 'orm', 'icon': 'boxes',
|
|
144
|
+
'children': [
|
|
145
|
+
{'label': app, 'value': app, 'icon': 'box', 'children': mapping['orm'][app]}
|
|
146
|
+
for app in mapping['orm']
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return ValarResponse([orm, mon])
|
valar/views/rest.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from .handler import batch_handler
|
|
4
|
+
from ..channels.executer import execute_channel
|
|
5
|
+
from ..channels.sender import ValarChannelSender
|
|
6
|
+
from ..classes.valar_response import ValarResponse
|
|
7
|
+
from ..dao import Dao
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def batch(request):
|
|
11
|
+
sender = ValarChannelSender(request)
|
|
12
|
+
await execute_channel(batch_handler, sender)
|
|
13
|
+
return ValarResponse(True)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def save_one(request, db, entity):
|
|
17
|
+
item = json.loads(request.body)
|
|
18
|
+
dao = Dao(entity, db)
|
|
19
|
+
bean = dao.save_one(item)
|
|
20
|
+
item = dao.serialize(bean)
|
|
21
|
+
return ValarResponse(item)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def values(request, db, entity):
|
|
25
|
+
body = json.loads(request.body)
|
|
26
|
+
dao = Dao(entity, db)
|
|
27
|
+
conditions = body.get('conditions', [])
|
|
28
|
+
props = body.get('props', ['id'])
|
|
29
|
+
array = dao.values(conditions, props)
|
|
30
|
+
return ValarResponse(array)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def delete_one(request, db, entity):
|
|
34
|
+
body = json.loads(request.body)
|
|
35
|
+
_id = body['id']
|
|
36
|
+
dao = Dao(entity, db)
|
|
37
|
+
flag = dao.delete_one(_id)
|
|
38
|
+
return ValarResponse(flag)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def find_one(request, db, entity):
|
|
42
|
+
body = json.loads(request.body)
|
|
43
|
+
_id = body['id']
|
|
44
|
+
dao = Dao(entity, db)
|
|
45
|
+
bean = dao.find_one(_id)
|
|
46
|
+
item = dao.serialize(bean)
|
|
47
|
+
return ValarResponse(item)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def find(request, db, entity):
|
|
51
|
+
conditions = json.loads(request.body)
|
|
52
|
+
dao = Dao(entity, db)
|
|
53
|
+
results, _ = dao.find(conditions)
|
|
54
|
+
results = dao.serialize(results)
|
|
55
|
+
return ValarResponse(results)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def update(request, db, entity):
|
|
59
|
+
body = json.loads(request.body)
|
|
60
|
+
conditions = body.get('conditions', [])
|
|
61
|
+
template = body.get('template')
|
|
62
|
+
dao = Dao(entity, db)
|
|
63
|
+
flag = dao.update(template, conditions)
|
|
64
|
+
return ValarResponse(flag)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def search(request, db, entity):
|
|
68
|
+
body = json.loads(request.body)
|
|
69
|
+
_type = body.get('type')
|
|
70
|
+
orders = body.get('orders')
|
|
71
|
+
size = body.get('size')
|
|
72
|
+
page = body.get('page')
|
|
73
|
+
root = body.get('root')
|
|
74
|
+
code = body.get('code', 'default')
|
|
75
|
+
conditions = body.get('conditions')
|
|
76
|
+
dao = Dao(entity, db)
|
|
77
|
+
|
|
78
|
+
if _type == 'tree':
|
|
79
|
+
query_set = dao.tree(root, conditions)
|
|
80
|
+
total = query_set.count()
|
|
81
|
+
else:
|
|
82
|
+
query_set, total = dao.find(conditions, orders, size, page)
|
|
83
|
+
results = dao.serialize(query_set, code)
|
|
84
|
+
|
|
85
|
+
return ValarResponse({
|
|
86
|
+
"results": results,
|
|
87
|
+
"type": _type,
|
|
88
|
+
"total": total,
|
|
89
|
+
"root": root
|
|
90
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: valar
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: valar for morghulis
|
|
5
5
|
Home-page: https://gitee.com/GRIFFIN120/valar_dev
|
|
6
6
|
Author: LYP
|
|
@@ -27,12 +27,13 @@ Dynamic: requires-python
|
|
|
27
27
|
Dynamic: summary
|
|
28
28
|
|
|
29
29
|
valar for morghulis
|
|
30
|
+
|
|
30
31
|
# 1. install
|
|
32
|
+
|
|
31
33
|
```shell
|
|
32
34
|
pip install valar
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
36
37
|
# 1. settings
|
|
37
38
|
|
|
38
39
|
```python
|
|
@@ -47,16 +48,12 @@ BASE_APP = str(BASE_DIR.name)
|
|
|
47
48
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
48
49
|
SECRET_KEY = get_random_secret_key()
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
51
|
""" Valar Options """
|
|
53
52
|
|
|
54
53
|
HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
55
54
|
MONGO_URI = 'mongodb://root:19870120@121.41.111.175:27017/'
|
|
56
55
|
MINIO_URL = "s3://admin:password@120.27.8.186:9000"
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
57
|
""" Minimized compulsory settings """
|
|
61
58
|
|
|
62
59
|
DATABASES = {
|
|
@@ -69,7 +66,7 @@ INSTALLED_APPS = [
|
|
|
69
66
|
'django.contrib.sessions',
|
|
70
67
|
"corsheaders",
|
|
71
68
|
'channels',
|
|
72
|
-
'valar',
|
|
69
|
+
'valar.apps.ValarConfig',
|
|
73
70
|
]
|
|
74
71
|
MIDDLEWARE = [
|
|
75
72
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
@@ -99,6 +96,7 @@ FILE_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
|
99
96
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 100
|
|
100
97
|
|
|
101
98
|
```
|
|
99
|
+
|
|
102
100
|
# 2. asgi
|
|
103
101
|
|
|
104
102
|
```python
|
|
@@ -117,8 +115,8 @@ application = ProtocolTypeRouter({
|
|
|
117
115
|
```
|
|
118
116
|
|
|
119
117
|
# 3. migrate
|
|
120
|
-
no need, valar will auto migration
|
|
121
118
|
|
|
119
|
+
no need, valar will auto migration
|
|
122
120
|
|
|
123
121
|
# 4. root urls
|
|
124
122
|
|
|
@@ -126,7 +124,6 @@ no need, valar will auto set urlpatterns
|
|
|
126
124
|
|
|
127
125
|
# 5. how to use valar_channel
|
|
128
126
|
|
|
129
|
-
|
|
130
127
|
5.1 set HANDLER_MAPPING in settings
|
|
131
128
|
|
|
132
129
|
```python
|
|
@@ -137,13 +134,11 @@ HANDLER_MAPPING = "%s.urls.channel_mapping" % BASE_APP
|
|
|
137
134
|
|
|
138
135
|
```python
|
|
139
136
|
from valar.channels.sender import ValarSocketSender
|
|
137
|
+
|
|
138
|
+
|
|
140
139
|
def test_handler(sender: ValarSocketSender):
|
|
141
140
|
data = sender.data
|
|
142
|
-
|
|
143
|
-
counter = sender.create_counter(length)
|
|
144
|
-
for i in range(length):
|
|
145
|
-
# sync method
|
|
146
|
-
sender.to_clients(counter.tick() ,sender.client, wait=True)
|
|
141
|
+
sender.load(data)
|
|
147
142
|
```
|
|
148
143
|
|
|
149
144
|
5.3 register handler in channel_mapping
|