valar 1.1.4__tar.gz → 1.2.0__tar.gz
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-1.1.4/src/valar.egg-info → valar-1.2.0}/PKG-INFO +1 -1
- {valar-1.1.4 → valar-1.2.0}/setup.py +4 -4
- valar-1.2.0/src/valar/apps.py +18 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/channels/consumer.py +10 -12
- valar-1.2.0/src/valar/channels/executer.py +14 -0
- valar-1.2.0/src/valar/channels/sender.py +116 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/channels/views.py +2 -3
- {valar-1.1.4/src/valar/classes → valar-1.2.0/src/valar/classes/app_mixins}/auto_urlpatterns_mixin.py +3 -3
- valar-1.2.0/src/valar/classes/valar_minio.py +80 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/classes/valar_response.py +2 -1
- valar-1.2.0/src/valar/dao/__init__.py +45 -0
- valar-1.2.0/src/valar/dao/abstract.py +106 -0
- valar-1.2.0/src/valar/dao/defaults/field_keys_default.py +48 -0
- valar-1.2.0/src/valar/dao/defaults/field_values_default.py +135 -0
- valar-1.2.0/src/valar/dao/defaults/view_defaults.py +26 -0
- valar-1.2.0/src/valar/dao/engine.py +80 -0
- valar-1.2.0/src/valar/dao/frame.py +189 -0
- valar-1.2.0/src/valar/dao/meta.py +128 -0
- valar-1.2.0/src/valar/dao/mon_dao.py +113 -0
- valar-1.2.0/src/valar/dao/mon_field.py +23 -0
- valar-1.2.0/src/valar/dao/orm_dao.py +304 -0
- valar-1.2.0/src/valar/dao/orm_field.py +142 -0
- valar-1.2.0/src/valar/dao/query.py +36 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/migrations/0001_initial.py +25 -17
- {valar-1.1.4 → valar-1.2.0}/src/valar/models/core.py +16 -10
- {valar-1.1.4 → valar-1.2.0}/src/valar/models/frame.py +4 -7
- {valar-1.1.4 → valar-1.2.0}/src/valar/models/meta.py +19 -16
- valar-1.2.0/src/valar/urls.py +29 -0
- valar-1.2.0/src/valar/views/__init__.py +0 -0
- valar-1.2.0/src/valar/views/file.py +49 -0
- valar-1.2.0/src/valar/views/handler.py +33 -0
- valar-1.2.0/src/valar/views/meta.py +150 -0
- valar-1.2.0/src/valar/views/rest.py +90 -0
- {valar-1.1.4 → valar-1.2.0/src/valar.egg-info}/PKG-INFO +1 -1
- valar-1.2.0/src/valar.egg-info/SOURCES.txt +50 -0
- valar-1.1.4/src/valar/apps.py +0 -21
- valar-1.1.4/src/valar/channels/executer.py +0 -13
- valar-1.1.4/src/valar/channels/sender.py +0 -64
- valar-1.1.4/src/valar/urls.py +0 -7
- valar-1.1.4/src/valar.egg-info/SOURCES.txt +0 -31
- {valar-1.1.4 → valar-1.2.0}/LICENSE +0 -0
- {valar-1.1.4 → valar-1.2.0}/README.md +0 -0
- {valar-1.1.4 → valar-1.2.0}/setup.cfg +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/channels/__init__.py +0 -0
- {valar-1.1.4/src/valar/classes → valar-1.2.0/src/valar/channels}/counter.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/channels/mapping.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/classes/__init__.py +0 -0
- {valar-1.1.4/src/valar/frame → valar-1.2.0/src/valar/classes/app_mixins}/__init__.py +0 -0
- {valar-1.1.4/src/valar/classes → valar-1.2.0/src/valar/classes/app_mixins}/auto_migration_mixin.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/classes/singleton_meta.py +0 -0
- {valar-1.1.4/src/valar/migrations → valar-1.2.0/src/valar/dao/defaults}/__init__.py +0 -0
- {valar-1.1.4/src/valar/views → valar-1.2.0/src/valar/migrations}/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar/models/__init__.py +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar.egg-info/dependency_links.txt +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar.egg-info/requires.txt +0 -0
- {valar-1.1.4 → valar-1.2.0}/src/valar.egg-info/top_level.txt +0 -0
|
@@ -16,16 +16,16 @@ requires = [
|
|
|
16
16
|
|
|
17
17
|
setup(
|
|
18
18
|
name="valar", # 包名
|
|
19
|
-
version="1.
|
|
19
|
+
version="1.2.0", # 版本号
|
|
20
20
|
author="LYP", # 作者
|
|
21
21
|
author_email="liuyinpeng@buaa.edu.cn", # 邮箱
|
|
22
22
|
description="valar for morghulis", # 简短描述
|
|
23
23
|
long_description=long_description, # 详细说明
|
|
24
24
|
long_description_content_type="text/markdown", # 详细说明使用标记类型
|
|
25
|
-
url="https://gitee.com/GRIFFIN120/valar_dev",
|
|
25
|
+
url="https://gitee.com/GRIFFIN120/valar_dev", # 项目主页
|
|
26
26
|
packages=find_packages(where="src"), # 需要打包的部分
|
|
27
27
|
package_dir={"": "src"}, # 设置src目录为根目录
|
|
28
28
|
python_requires=">=3.9", # 项目支持的Python版本
|
|
29
|
-
install_requires=requires,
|
|
29
|
+
install_requires=requires, # 项目必须的依赖
|
|
30
30
|
include_package_data=False # 是否包含非Python文件(如资源文件)
|
|
31
|
-
)
|
|
31
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from django.apps import AppConfig
|
|
3
|
+
from .classes.app_mixins.auto_migration_mixin import AutoMigrationMixin
|
|
4
|
+
from .classes.app_mixins.auto_urlpatterns_mixin import AutoUrlPatternsMixin
|
|
5
|
+
|
|
6
|
+
valar_app = __package__.replace('src.', '')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValarConfig(AutoMigrationMixin, AutoUrlPatternsMixin, AppConfig):
|
|
10
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
|
11
|
+
name = __package__
|
|
12
|
+
|
|
13
|
+
def ready(self):
|
|
14
|
+
if os.environ.get('RUN_MAIN') == 'true':
|
|
15
|
+
from .dao.frame import MetaFrame
|
|
16
|
+
getattr(super(), 'set_url', None)()
|
|
17
|
+
getattr(super(), 'auto_migrate', None)()
|
|
18
|
+
MetaFrame()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
1
|
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
|
3
2
|
|
|
4
3
|
VALAR_CHANNEL_GROUP = 'VALAR'
|
|
5
4
|
|
|
5
|
+
|
|
6
6
|
class ValarConsumer(AsyncJsonWebsocketConsumer):
|
|
7
7
|
|
|
8
8
|
def __init__(self):
|
|
@@ -24,25 +24,23 @@ class ValarConsumer(AsyncJsonWebsocketConsumer):
|
|
|
24
24
|
pass
|
|
25
25
|
|
|
26
26
|
async def user_emit(self, event):
|
|
27
|
-
users: list = event.get('users',[])
|
|
28
|
-
data = event.get('data',{})
|
|
27
|
+
users: list = event.get('users', [])
|
|
28
|
+
data = event.get('data', {})
|
|
29
29
|
if self.uid in users:
|
|
30
30
|
await self.send_json(data)
|
|
31
31
|
|
|
32
32
|
async def client_emit(self, event):
|
|
33
|
-
clients: list = event.get('clients',[])
|
|
34
|
-
data = event.get('data',{})
|
|
33
|
+
clients: list = event.get('clients', [])
|
|
34
|
+
data = event.get('data', {})
|
|
35
35
|
if self.client in clients:
|
|
36
36
|
await self.send_json(data)
|
|
37
37
|
|
|
38
38
|
async def broadcast_emit(self, event):
|
|
39
|
-
data = event.get('data',{})
|
|
39
|
+
data = event.get('data', {})
|
|
40
40
|
await self.send_json(data)
|
|
41
41
|
|
|
42
42
|
async def register_emit(self, event):
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if self.client
|
|
46
|
-
self.uid =
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
uid = event.get('uid', )
|
|
44
|
+
client = event.get('client')
|
|
45
|
+
if self.client == client:
|
|
46
|
+
self.uid = uid
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from ..channels.sender import ValarChannelSender
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def execute_channel(method, sender: ValarChannelSender):
|
|
7
|
+
thread = asyncio.to_thread(__execute__, method, sender)
|
|
8
|
+
asyncio.create_task(thread)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def __execute__(method, sender: ValarChannelSender):
|
|
12
|
+
sender.start()
|
|
13
|
+
method(sender)
|
|
14
|
+
sender.stop()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from asgiref.sync import async_to_sync
|
|
6
|
+
from channels.layers import get_channel_layer
|
|
7
|
+
from django.http import HttpRequest
|
|
8
|
+
import threading
|
|
9
|
+
from .consumer import VALAR_CHANNEL_GROUP
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Channel:
|
|
13
|
+
|
|
14
|
+
def __init__(self, request: HttpRequest):
|
|
15
|
+
body = json.loads(request.body)
|
|
16
|
+
self.handler = body.get('handler')
|
|
17
|
+
self.url = body.get('url')
|
|
18
|
+
self.auth = body.get('auth')
|
|
19
|
+
self.broadcast = body.get('broadcast')
|
|
20
|
+
self.data = body.get('data')
|
|
21
|
+
|
|
22
|
+
def to_dict(self, status, payload):
|
|
23
|
+
data = {
|
|
24
|
+
'handler': self.handler,
|
|
25
|
+
'url': self.url,
|
|
26
|
+
'auth': self.auth,
|
|
27
|
+
'broadcast': self.broadcast,
|
|
28
|
+
'timestamp': datetime.now().timestamp()
|
|
29
|
+
}
|
|
30
|
+
if status:
|
|
31
|
+
data.update({'status': status})
|
|
32
|
+
if payload:
|
|
33
|
+
data.update({'payload': payload})
|
|
34
|
+
return data
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Sender:
|
|
38
|
+
|
|
39
|
+
def __init__(self, request: HttpRequest):
|
|
40
|
+
self.client = request.headers.get('CLIENT')
|
|
41
|
+
self.uid = request.session.get('UID')
|
|
42
|
+
self.group_send = async_to_sync(get_channel_layer().group_send)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ValarChannelSender(Sender):
|
|
46
|
+
|
|
47
|
+
def __init__(self, request: HttpRequest, interval=1):
|
|
48
|
+
super().__init__(request)
|
|
49
|
+
self.__channel__ = Channel(request)
|
|
50
|
+
self.data = self.__channel__.data
|
|
51
|
+
self.__payload__ = None
|
|
52
|
+
self.__loading__ = False
|
|
53
|
+
self.__thread__ = None
|
|
54
|
+
self.__lock__ = threading.Lock()
|
|
55
|
+
self.__interval__ = interval
|
|
56
|
+
if self.__channel__.auth and not self.uid:
|
|
57
|
+
raise Exception('Unauthorized!')
|
|
58
|
+
|
|
59
|
+
def _run(self):
|
|
60
|
+
while self.__loading__:
|
|
61
|
+
self.__emit__()
|
|
62
|
+
time.sleep(self.__interval__)
|
|
63
|
+
|
|
64
|
+
def start(self):
|
|
65
|
+
if self.__loading__:
|
|
66
|
+
return # 避免重复启动
|
|
67
|
+
self.__payload__ = None
|
|
68
|
+
self.__loading__ = True
|
|
69
|
+
self.__emit__('start')
|
|
70
|
+
self.__thread__ = threading.Thread(target=self._run, daemon=True)
|
|
71
|
+
self.__thread__.start()
|
|
72
|
+
|
|
73
|
+
def stop(self):
|
|
74
|
+
self.__payload__ = None
|
|
75
|
+
self.__loading__ = False
|
|
76
|
+
self.__emit__('stop')
|
|
77
|
+
if self.__thread__:
|
|
78
|
+
self.__thread__.join()
|
|
79
|
+
self.__thread__ = None
|
|
80
|
+
|
|
81
|
+
def load(self, payload):
|
|
82
|
+
with self.__lock__:
|
|
83
|
+
self.__payload__ = payload
|
|
84
|
+
|
|
85
|
+
def done(self, payload):
|
|
86
|
+
self.__emit__('done', payload)
|
|
87
|
+
|
|
88
|
+
def __emit__(self, status='proceed', data=None):
|
|
89
|
+
scope = 'broadcast' if self.__channel__.broadcast else 'client'
|
|
90
|
+
body = {
|
|
91
|
+
'type': f'{scope}.emit',
|
|
92
|
+
'data': self.__channel__.to_dict(status, data or self.__payload__),
|
|
93
|
+
'clients': [self.client],
|
|
94
|
+
'users': []
|
|
95
|
+
}
|
|
96
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ValarSocketSender(Sender):
|
|
100
|
+
def __init__(self, request: HttpRequest):
|
|
101
|
+
super().__init__(request)
|
|
102
|
+
if self.uid:
|
|
103
|
+
body = {'type': 'broadcast.emit', 'uid': self.uid, 'client': self.client}
|
|
104
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
105
|
+
|
|
106
|
+
def to_users(self, payload, users: list):
|
|
107
|
+
body = {'type': 'user.emit', 'data': payload, 'users': users}
|
|
108
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
109
|
+
|
|
110
|
+
def to_clients(self, payload, clients: list):
|
|
111
|
+
body = {'type': 'client.emit', 'data': payload, 'clients': clients}
|
|
112
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
113
|
+
|
|
114
|
+
def broadcast(self, payload):
|
|
115
|
+
body = {'type': 'broadcast.emit', 'data': payload}
|
|
116
|
+
self.group_send(VALAR_CHANNEL_GROUP, body)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
from .executer import execute_channel
|
|
3
2
|
from .mapping import ChannelMapping
|
|
4
|
-
from .sender import
|
|
3
|
+
from .sender import ValarChannelSender
|
|
5
4
|
from ..classes.valar_response import ValarResponse
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
async def handel_channel(request, handler):
|
|
9
|
-
sender =
|
|
8
|
+
sender = ValarChannelSender(request)
|
|
10
9
|
method = ChannelMapping().get_handler(handler)
|
|
11
10
|
await execute_channel(method, sender)
|
|
12
11
|
return ValarResponse(True)
|
{valar-1.1.4/src/valar/classes → valar-1.2.0/src/valar/classes/app_mixins}/auto_urlpatterns_mixin.py
RENAMED
|
@@ -3,13 +3,13 @@ import importlib
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.urls import path, include
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
class AutoUrlPatternsMixin:
|
|
7
8
|
name = None # 子类必须提供
|
|
9
|
+
|
|
8
10
|
def set_url(self):
|
|
9
11
|
root = settings.ROOT_URLCONF
|
|
10
12
|
module = importlib.import_module(root)
|
|
11
13
|
urlpatterns: list = getattr(module, 'urlpatterns')
|
|
12
14
|
url = f'{self.name}.urls'
|
|
13
|
-
urlpatterns.append(path('
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
urlpatterns.append(path('valar/', include(url)))
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from urllib3 import BaseHTTPResponse
|
|
5
|
+
|
|
6
|
+
from ..classes.singleton_meta import SingletonMeta
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValarMinio(metaclass=SingletonMeta):
|
|
10
|
+
|
|
11
|
+
def __init__(self, client, entity):
|
|
12
|
+
self.client = client
|
|
13
|
+
self.bucket_name = f'{settings.BASE_DIR.name}.{entity}'.replace('_', '-').lower()
|
|
14
|
+
if client and not self.client.bucket_exists(self.bucket_name):
|
|
15
|
+
self.client.make_bucket(self.bucket_name)
|
|
16
|
+
self.client.set_bucket_policy(self.bucket_name, self.__generate_policy__())
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def get_object_name(_id, prop, file_name):
|
|
20
|
+
return f"{_id}-{prop}-{file_name}"
|
|
21
|
+
|
|
22
|
+
def upload(self, object_name, _bytes):
|
|
23
|
+
file_data = BytesIO(_bytes)
|
|
24
|
+
file_size = len(_bytes) # file.siz
|
|
25
|
+
self.client.put_object(
|
|
26
|
+
bucket_name=self.bucket_name,
|
|
27
|
+
object_name=object_name,
|
|
28
|
+
data=file_data,
|
|
29
|
+
length=file_size
|
|
30
|
+
)
|
|
31
|
+
return f'{self.bucket_name}/{object_name}'
|
|
32
|
+
|
|
33
|
+
def remove(self, path):
|
|
34
|
+
if path:
|
|
35
|
+
bucket_name, object_name = path.split('/')
|
|
36
|
+
self.client.remove_object(
|
|
37
|
+
bucket_name=bucket_name,
|
|
38
|
+
object_name=object_name
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def read(self, object_name) -> BytesIO:
|
|
42
|
+
ret: BaseHTTPResponse = self.client.get_object(
|
|
43
|
+
bucket_name=self.bucket_name,
|
|
44
|
+
object_name=object_name
|
|
45
|
+
)
|
|
46
|
+
return BytesIO(ret.read())
|
|
47
|
+
|
|
48
|
+
def __generate_policy__(self):
|
|
49
|
+
return json.dumps({
|
|
50
|
+
"Version": "2012-10-17",
|
|
51
|
+
"Statement": [
|
|
52
|
+
{
|
|
53
|
+
"Sid": "",
|
|
54
|
+
"Effect": "Allow",
|
|
55
|
+
"Principal": {"AWS": "*"},
|
|
56
|
+
"Action": "s3:GetBucketLocation",
|
|
57
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"Sid": "",
|
|
61
|
+
"Effect": "Allow",
|
|
62
|
+
"Principal": {"AWS": "*"},
|
|
63
|
+
"Action": "s3:ListBucket",
|
|
64
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"Sid": "",
|
|
68
|
+
"Effect": "Allow",
|
|
69
|
+
"Principal": {"AWS": "*"},
|
|
70
|
+
"Action": "s3:GetObject",
|
|
71
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}/*"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"Sid": "",
|
|
75
|
+
"Effect": "Allow",
|
|
76
|
+
"Principal": {"AWS": "*"},
|
|
77
|
+
"Action": "s3:PutObject",
|
|
78
|
+
"Resource": f"arn:aws:s3:::{self.bucket_name}/*"
|
|
79
|
+
}
|
|
80
|
+
]})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from django.http import JsonResponse
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
class ValarResponse(JsonResponse):
|
|
4
|
-
def __init__(self, data, message='', code='info'):
|
|
5
|
+
def __init__(self, data=True, message='', code='info'):
|
|
5
6
|
self.message = message
|
|
6
7
|
self.code = code
|
|
7
8
|
super(ValarResponse, self).__init__(data, safe=False)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from ..dao.abstract import AbstractDao
|
|
2
|
+
from ..dao.mon_dao import MonDao
|
|
3
|
+
from ..dao.orm_dao import OrmDao
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Dao(AbstractDao):
|
|
7
|
+
|
|
8
|
+
def __init__(self, entity, db='orm'):
|
|
9
|
+
self.dao = OrmDao(entity) if db == 'orm' else MonDao(entity)
|
|
10
|
+
self.db = db
|
|
11
|
+
self.entity = entity
|
|
12
|
+
self.name = self.dao.name
|
|
13
|
+
self.is_tree = self.dao.is_tree
|
|
14
|
+
self.fields = self.dao.fields
|
|
15
|
+
self.manager = self.dao.manager
|
|
16
|
+
|
|
17
|
+
def save_many(self, array: list):
|
|
18
|
+
self.dao.save_many(array)
|
|
19
|
+
|
|
20
|
+
def save_one(self, item, with_id=False):
|
|
21
|
+
return self.dao.save_one(item, with_id)
|
|
22
|
+
|
|
23
|
+
def delete_one(self, _id):
|
|
24
|
+
return self.dao.delete_one(_id)
|
|
25
|
+
|
|
26
|
+
def find_one(self, _id):
|
|
27
|
+
return self.dao.find_one(_id)
|
|
28
|
+
|
|
29
|
+
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
30
|
+
return self.dao.find(conditions, orders, size, page)
|
|
31
|
+
|
|
32
|
+
def values(self, conditions, props):
|
|
33
|
+
return self.dao.values(conditions, props)
|
|
34
|
+
|
|
35
|
+
def update(self, template, conditions):
|
|
36
|
+
return self.dao.update(template, conditions)
|
|
37
|
+
|
|
38
|
+
def delete(self, conditions=None) -> list:
|
|
39
|
+
return self.dao.delete(conditions)
|
|
40
|
+
|
|
41
|
+
def serialize(self, o, code=None):
|
|
42
|
+
return self.dao.serialize(o, code)
|
|
43
|
+
|
|
44
|
+
def tree(self, root, conditions=None):
|
|
45
|
+
return self.dao.tree(root, conditions)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from bson import ObjectId
|
|
4
|
+
|
|
5
|
+
from ..dao.engine import ValarEngine
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AbstractField(ABC):
|
|
9
|
+
db = None
|
|
10
|
+
entity = None
|
|
11
|
+
prop = None
|
|
12
|
+
label = None
|
|
13
|
+
domain = None
|
|
14
|
+
refer = None
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def to_dict(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AbstractDao(ABC):
|
|
22
|
+
engine = ValarEngine()
|
|
23
|
+
db = None
|
|
24
|
+
entity = None
|
|
25
|
+
name = None
|
|
26
|
+
is_tree = False
|
|
27
|
+
fields = {}
|
|
28
|
+
|
|
29
|
+
def props(self, domain=None):
|
|
30
|
+
return [prop for prop, field in self.fields.items() if field.domain == domain or domain is None]
|
|
31
|
+
|
|
32
|
+
def full_props(self):
|
|
33
|
+
return {
|
|
34
|
+
prop: {
|
|
35
|
+
"prop": prop,
|
|
36
|
+
"domain": field.domain,
|
|
37
|
+
"label": field.label,
|
|
38
|
+
}
|
|
39
|
+
for prop, field in self.fields.items()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
def get_meta_field(self, prop) -> AbstractField:
|
|
43
|
+
return self.fields[prop]
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def save_one(self, item, with_id=False):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def save_many(self, array: list):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def values(self, conditions, props):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def delete_one(self, _id):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def find_one(self, _id):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
def update(self, template, conditions):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def delete(self, conditions=None) -> list:
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def serialize(self, o, code=None):
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def tree(self, root, conditions=None):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
def search(self, includes=None, excludes=None, orders=None):
|
|
86
|
+
conditions = [{"includes": includes or {}, "excludes": excludes or {}}]
|
|
87
|
+
results, _ = self.find(conditions, orders)
|
|
88
|
+
return results
|
|
89
|
+
|
|
90
|
+
def object_id(self, _id):
|
|
91
|
+
try:
|
|
92
|
+
return int(_id) if self.db == 'orm' else ObjectId(_id)
|
|
93
|
+
except Exception:
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
# @abstractmethod
|
|
97
|
+
# def values(self, props, conditions, orders=None):
|
|
98
|
+
# pass
|
|
99
|
+
#
|
|
100
|
+
# @abstractmethod
|
|
101
|
+
# def group(self, props, conditions, orders=None):
|
|
102
|
+
# pass
|
|
103
|
+
#
|
|
104
|
+
# @abstractmethod
|
|
105
|
+
# def count(self, props, conditions):
|
|
106
|
+
# pass
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
meta_field_key_defaults = {
|
|
2
|
+
'valar.Meta': {
|
|
3
|
+
'default': ('pick', ['db', 'entity', 'name', 'tree']),
|
|
4
|
+
},
|
|
5
|
+
'valar.MetaView': {
|
|
6
|
+
'list': ('pick', ['code', 'name']),
|
|
7
|
+
'core': ('pick', ['name', 'enable', 'lock', 'property']),
|
|
8
|
+
'style': ('pick', ['form_width', 'form_height', 'table_width', 'table_height']),
|
|
9
|
+
'rest': ('pick',
|
|
10
|
+
['allow_search', 'allow_order', 'allow_insert', 'allow_remove', 'allow_download', 'allow_upload']),
|
|
11
|
+
'edit': ('pick', ['allow_edit', 'allow_edit_on_form', 'allow_edit_on_cell', 'allow_edit_on_sort']),
|
|
12
|
+
},
|
|
13
|
+
'valar.MetaField': {
|
|
14
|
+
'tool': (
|
|
15
|
+
'pick',
|
|
16
|
+
[
|
|
17
|
+
'name', 'domain', 'tool', 'refer', 'format'
|
|
18
|
+
]
|
|
19
|
+
),
|
|
20
|
+
'rest': (
|
|
21
|
+
'pick',
|
|
22
|
+
[
|
|
23
|
+
'name', 'not_null',
|
|
24
|
+
'allow_edit', 'allow_sort', 'allow_search', 'allow_download', 'allow_upload', 'allow_update'
|
|
25
|
+
]
|
|
26
|
+
),
|
|
27
|
+
'table': (
|
|
28
|
+
'pick',
|
|
29
|
+
[
|
|
30
|
+
'name', 'unit', 'column_width', 'fixed', 'align', 'edit_on_table', 'hide_on_table',
|
|
31
|
+
'header_color', 'cell_color'
|
|
32
|
+
]
|
|
33
|
+
),
|
|
34
|
+
'form': (
|
|
35
|
+
'pick',
|
|
36
|
+
[
|
|
37
|
+
'name', 'span',
|
|
38
|
+
'hide_on_form', 'hide_on_form_insert', 'hide_on_form_edit', 'hide_on_form_branch', 'hide_on_form_leaf'
|
|
39
|
+
]
|
|
40
|
+
),
|
|
41
|
+
},
|
|
42
|
+
'vtest.Vala': {
|
|
43
|
+
'simple': ('pick', ['id', 'name', 'text_field', 'boolean_field', 'integer_field', 'float_field']),
|
|
44
|
+
'date': ('pick', ['id', 'name', 'date_field', 'datetime_field', 'time_field']),
|
|
45
|
+
'special': ('pick', ['id', 'name', 'text_field', 'json_field', 'file', 'm2m']),
|
|
46
|
+
'ref': ('pick', ['id', 'name', 'm2o', 'm2m', 'o2o_id']),
|
|
47
|
+
},
|
|
48
|
+
}
|
|
@@ -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
|
+
}
|