valar 1.0.21__py3-none-any.whl → 1.0.22__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/__init__.py +0 -26
- valar/channels/__init__.py +1 -107
- valar/channels/consumer.py +48 -0
- valar/channels/executer.py +13 -0
- valar/channels/mapping.py +21 -0
- valar/channels/sender.py +60 -0
- valar/channels/views.py +6 -11
- valar/core/__init__.py +0 -0
- valar/core/counter.py +9 -0
- valar/core/dao/__init__.py +0 -0
- valar/core/dao/_mon_array2tree.py +18 -0
- valar/core/dao/dao_base.py +50 -0
- valar/core/dao/dao_mon.py +76 -0
- valar/core/dao/dao_orm.py +96 -0
- valar/core/dao/engine.py +12 -0
- valar/core/dao/engine_minio.py +90 -0
- valar/core/dao/engine_mon.py +34 -0
- valar/core/dao/engine_orm.py +25 -0
- valar/core/dao/model_mon.py +24 -0
- valar/core/dao/model_orm.py +192 -0
- valar/core/dao/query_mon.py +12 -0
- valar/core/dao/query_orm.py +43 -0
- valar/core/dao/utils_orm.py +85 -0
- valar/core/dao_abstract.py +63 -0
- valar/core/meta/__init__.py +0 -0
- valar/core/meta/defaults/__init__.py +0 -0
- valar/core/meta/defaults/field_keys_default.py +17 -0
- valar/core/meta/defaults/field_values_default.py +85 -0
- valar/core/meta/defaults/frame_defaults.py +136 -0
- valar/core/meta/defaults/view_defaults.py +7 -0
- valar/core/meta/field_orm.py +144 -0
- valar/core/meta/init_meta_frame.py +30 -0
- valar/core/meta/meta_orm.py +69 -0
- valar/core/middleware.py +20 -0
- valar/core/response.py +7 -0
- valar/core/singleton_meta.py +6 -0
- valar/core/valar_models.py +82 -0
- valar/data/apps.py +22 -0
- valar/data/migrations/0001_initial.py +141 -0
- valar/data/models.py +2 -121
- valar/data/urls.py +15 -21
- valar/data/views/__init__.py +0 -0
- valar/data/views/handler.py +41 -0
- valar/data/views/rest.py +86 -0
- {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/METADATA +1 -1
- valar-1.0.22.dist-info/RECORD +51 -0
- {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/WHEEL +1 -1
- valar/channels/utils.py +0 -43
- valar/data/file/__init__.py +0 -91
- valar/data/handlers.py +0 -28
- valar/data/mon/__init__.py +0 -123
- valar/data/mon/query_translator.py +0 -91
- valar/data/orm/__init__.py +0 -135
- valar/data/orm/detacher.py +0 -61
- valar/data/orm/meta.py +0 -99
- valar/data/orm/meta_frame.py +0 -100
- valar/data/orm/meta_loader.py +0 -200
- valar/data/orm/values.py +0 -102
- valar/data/query.py +0 -48
- valar/data/utils.py +0 -70
- valar/data/views.py +0 -173
- valar-1.0.21.dist-info/RECORD +0 -26
- {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/licenses/LICENSE +0 -0
- {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/top_level.txt +0 -0
valar/data/handlers.py
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
|
|
3
|
-
from ..channels import ValarSocketSender
|
|
4
|
-
from ..channels.utils import channel_wrapper
|
|
5
|
-
from ..data.utils import get_dao
|
|
6
|
-
|
|
7
|
-
@channel_wrapper
|
|
8
|
-
def save_many_handler(data, sender: ValarSocketSender):
|
|
9
|
-
start_time = time.time()
|
|
10
|
-
entity, array, db = data.get("entity"), data.get("array",[]), data.get("db")
|
|
11
|
-
dao = get_dao(db, entity)
|
|
12
|
-
index, length = 1, len(array)
|
|
13
|
-
for item in array:
|
|
14
|
-
item['saved'] = True
|
|
15
|
-
dao.save_one(item)
|
|
16
|
-
current_time = time.time()
|
|
17
|
-
time_span = current_time - start_time
|
|
18
|
-
if time_span > 1:
|
|
19
|
-
start_time = current_time
|
|
20
|
-
send(index, length, sender)
|
|
21
|
-
index += 1
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def send(index, length, sender):
|
|
26
|
-
percentage = round(index * 100 / length)
|
|
27
|
-
tick = {'length': length, 'index': index, 'percentage': percentage}
|
|
28
|
-
sender.to_clients(tick, sender.client)
|
valar/data/mon/__init__.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
from bson import ObjectId
|
|
2
|
-
from pymongo.results import InsertOneResult
|
|
3
|
-
|
|
4
|
-
from django.conf import settings
|
|
5
|
-
import pymongo
|
|
6
|
-
|
|
7
|
-
from ..query import Query
|
|
8
|
-
|
|
9
|
-
from pymongo import MongoClient
|
|
10
|
-
from typing import Dict, Any, List, Optional
|
|
11
|
-
|
|
12
|
-
try:
|
|
13
|
-
MONGO = settings.MONGO_SETTINGS
|
|
14
|
-
except AttributeError:
|
|
15
|
-
MONGO = {
|
|
16
|
-
'host': 'localhost',
|
|
17
|
-
'port': 27017,
|
|
18
|
-
}
|
|
19
|
-
host, port, username, password = MONGO.get('host'), MONGO.get('port'), MONGO.get('username'), MONGO.get('password')
|
|
20
|
-
|
|
21
|
-
if username and password:
|
|
22
|
-
uri = f'mongodb://{username}:{password}@{host}:{port}/'
|
|
23
|
-
else:
|
|
24
|
-
uri = f'mongodb://{host}:{port}/'
|
|
25
|
-
mongo_params = {
|
|
26
|
-
'maxPoolSize': 10,
|
|
27
|
-
'minPoolSize': 0,
|
|
28
|
-
'maxIdleTimeMS': 10000,
|
|
29
|
-
'connectTimeoutMS': 10000,
|
|
30
|
-
'socketTimeoutMS': 10000,
|
|
31
|
-
'serverSelectionTimeoutMS': 10000,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
def get_mongo_client():
|
|
35
|
-
client = pymongo.MongoClient(uri, **mongo_params)
|
|
36
|
-
client['admin'].command('ping')
|
|
37
|
-
return client
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class MongoDao:
|
|
42
|
-
def __init__(self, ref):
|
|
43
|
-
self.ref = ref
|
|
44
|
-
db_name = settings.BASE_APP
|
|
45
|
-
col_name = ref.replace('.', '_')
|
|
46
|
-
self.client = get_mongo_client()
|
|
47
|
-
self.collection = self.client[db_name][col_name]
|
|
48
|
-
def save_one(self, item):
|
|
49
|
-
_id = item.get('id', None)
|
|
50
|
-
_id = None if isinstance(_id, int) else _id
|
|
51
|
-
if _id is None:
|
|
52
|
-
bean:InsertOneResult = self.collection.insert_one(item)
|
|
53
|
-
_id = bean.inserted_id
|
|
54
|
-
self.collection.update_one({'_id': _id}, {'$set': {'sort':str(_id)}})
|
|
55
|
-
else:
|
|
56
|
-
del item['id']
|
|
57
|
-
_id = ObjectId(_id)
|
|
58
|
-
self.collection.update_one({'_id': _id}, {'$set': item})
|
|
59
|
-
return self.collection.find_one({'_id': _id})
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def update_many(self, query, template):
|
|
63
|
-
self.collection.update_many(query.mon_conditions(), {'$set': template})
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def delete_one(self, _id):
|
|
67
|
-
self.collection.delete_one({'_id': ObjectId(_id)})
|
|
68
|
-
|
|
69
|
-
def delete_many(self, query):
|
|
70
|
-
self.collection.delete_many(query.mon_conditions())
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def find_one(self, _id):
|
|
74
|
-
return self.collection.find_one({'_id': ObjectId(_id)})
|
|
75
|
-
|
|
76
|
-
def find_many(self, query: Query, size=0, page=1) :
|
|
77
|
-
skip = (page - 1) * size
|
|
78
|
-
condition = query.mon_conditions()
|
|
79
|
-
total = self.collection.count_documents(condition)
|
|
80
|
-
cursor = self.collection.find(condition)
|
|
81
|
-
|
|
82
|
-
sort_fields = []
|
|
83
|
-
for key, value in query.orders.items():
|
|
84
|
-
sort_direction = pymongo.DESCENDING if value == -1 else pymongo.ASCENDING
|
|
85
|
-
sort_fields.append((key, sort_direction))
|
|
86
|
-
|
|
87
|
-
if sort_fields:
|
|
88
|
-
cursor = cursor.sort(sort_fields)
|
|
89
|
-
|
|
90
|
-
if size:
|
|
91
|
-
cursor = cursor.skip(skip).limit(size)
|
|
92
|
-
|
|
93
|
-
return cursor, total
|
|
94
|
-
|
|
95
|
-
def meta(self):
|
|
96
|
-
one = self.collection.find_one()
|
|
97
|
-
return one
|
|
98
|
-
|
|
99
|
-
class MongoDBQuery:
|
|
100
|
-
#Mongo的查询
|
|
101
|
-
def __init__(self, connection_string: str, database_name: str):
|
|
102
|
-
self.client = MongoClient(connection_string)
|
|
103
|
-
self.db = self.client[database_name]
|
|
104
|
-
|
|
105
|
-
def find(self, collection: str, query: Dict[str, Any],
|
|
106
|
-
projection: Optional[Dict[str, Any]] = None,
|
|
107
|
-
sort: Optional[List[tuple]] = None,
|
|
108
|
-
limit: Optional[int] = None,
|
|
109
|
-
skip: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
110
|
-
cursor = self.db[collection].find(query, projection)
|
|
111
|
-
if sort:
|
|
112
|
-
cursor = cursor.sort(sort) #好像有警告……但是能跑
|
|
113
|
-
if skip:
|
|
114
|
-
cursor = cursor.skip(skip)
|
|
115
|
-
if limit:
|
|
116
|
-
cursor = cursor.limit(limit)
|
|
117
|
-
return list(cursor)
|
|
118
|
-
|
|
119
|
-
def count(self, collection: str, query: Dict[str, Any]) -> int:
|
|
120
|
-
return self.db[collection].count_documents(query)
|
|
121
|
-
|
|
122
|
-
def close(self):
|
|
123
|
-
self.client.close()
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
class MongoQueryTranslator:
|
|
2
|
-
# 将Django ORM查询操作符映射到MongoDB操作符的字典
|
|
3
|
-
MONGO_OPERATORS = {
|
|
4
|
-
'exact': lambda v, e: {'$ne': v} if e else v,
|
|
5
|
-
'iexact': lambda v, e: {'$not': {'$regex': f'^{v}$', '$options': 'i'}} if e else {'$regex': f'^{v}$', '$options': 'i'},
|
|
6
|
-
'contains': lambda v, e: {'$not': {'$regex': f'{v}'}} if e else {'$regex': f'{v}'},
|
|
7
|
-
'icontains': lambda v, e: {'$not': {'$regex': f'{v}', '$options': 'i'}} if e else {'$regex': f'{v}', '$options': 'i'},
|
|
8
|
-
'startswith': lambda v, e: {'$not': {'$regex': f'^{v}'}} if e else {'$regex': f'^{v}'},
|
|
9
|
-
'istartswith': lambda v, e: {'$not': {'$regex': f'^{v}', '$options': 'i'}} if e else {'$regex': f'^{v}', '$options': 'i'},
|
|
10
|
-
'endswith': lambda v, e: {'$not': {'$regex': f'{v}$'}} if e else {'$regex': f'{v}$'},
|
|
11
|
-
'iendswith': lambda v, e: {'$not': {'$regex': f'{v}$', '$options': 'i'}} if e else {'$regex': f'{v}$', '$options': 'i'},
|
|
12
|
-
'gt': lambda v, e: {'$not': {'$gt': v}} if e else {'$gt': v},
|
|
13
|
-
'gte': lambda v, e: {'$not': {'$gte': v}} if e else {'$gte': v},
|
|
14
|
-
'lt': lambda v, e: {'$not': {'$lt': v}} if e else {'$lt': v},
|
|
15
|
-
'lte': lambda v, e: {'$not': {'$lte': v}} if e else {'$lte': v},
|
|
16
|
-
'in': lambda v, e: {'$nin': v} if e else {'$in': v},
|
|
17
|
-
'exists': lambda v, e: {'$eq': None} if (e and bool(v)) or (not e and not bool(v)) else {'$ne': None},
|
|
18
|
-
'isnull': lambda v, e: {'$ne': None} if e else {'$eq': None},
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@classmethod
|
|
22
|
-
def process_field_query(cls, key, value, is_exclude=False):
|
|
23
|
-
"""处理单个字段查询"""
|
|
24
|
-
if '__' in key:
|
|
25
|
-
field, op = key.split('__', 1)
|
|
26
|
-
if op in cls.MONGO_OPERATORS:
|
|
27
|
-
return field, cls.MONGO_OPERATORS[op](value, is_exclude)
|
|
28
|
-
return key, {'$ne': value} if is_exclude else value
|
|
29
|
-
|
|
30
|
-
@classmethod
|
|
31
|
-
def process_condition(cls, condition_dict, is_exclude=False):
|
|
32
|
-
"""处理条件字典,返回MongoDB查询条件"""
|
|
33
|
-
return {field: query for field, query in
|
|
34
|
-
[cls.process_field_query(k, v, is_exclude) for k, v in condition_dict.items()]}
|
|
35
|
-
|
|
36
|
-
@classmethod
|
|
37
|
-
def process_finder(cls, finder):
|
|
38
|
-
"""处理finder字段,转换为MongoDB查询条件"""
|
|
39
|
-
if not finder:
|
|
40
|
-
return {}
|
|
41
|
-
mongo_query = {}
|
|
42
|
-
if 'term' in finder and finder['term'] and isinstance(finder['term'], str):
|
|
43
|
-
term = finder['term']
|
|
44
|
-
fields = finder.get('fields', [])
|
|
45
|
-
if fields:
|
|
46
|
-
mongo_query['$or'] = [{field: {'$regex': term, '$options': 'i'}} for field in fields]
|
|
47
|
-
else:
|
|
48
|
-
mongo_query['$text'] = {'$search': term}
|
|
49
|
-
if 'range' in finder:
|
|
50
|
-
for field, ranges in finder['range'].items():
|
|
51
|
-
field_query = {f'${op}': val for op, val in ranges.items() if op in ['gt', 'gte', 'lt', 'lte']}
|
|
52
|
-
if field_query:
|
|
53
|
-
mongo_query[field] = field_query
|
|
54
|
-
for query_type, operator in [('match', None), ('exists', '$ne')]:
|
|
55
|
-
if query_type in finder:
|
|
56
|
-
for field, value in finder[query_type].items():
|
|
57
|
-
if operator == '$ne':
|
|
58
|
-
# 处理exists查询,检查字段是否为空
|
|
59
|
-
mongo_query[field] = {'$ne': None} if bool(value) else {'$eq': None}
|
|
60
|
-
else:
|
|
61
|
-
mongo_query[field] = value
|
|
62
|
-
return mongo_query
|
|
63
|
-
|
|
64
|
-
@classmethod
|
|
65
|
-
def translate_query(cls, query_obj):
|
|
66
|
-
"""
|
|
67
|
-
将Query对象转换为MongoDB查询
|
|
68
|
-
Args:
|
|
69
|
-
query_obj: Query对象,包含condition, search和finder
|
|
70
|
-
Returns:
|
|
71
|
-
转换后的MongoDB查询条件
|
|
72
|
-
"""
|
|
73
|
-
query = {}
|
|
74
|
-
query.update(cls.process_condition(query_obj.condition.includes))
|
|
75
|
-
query.update(cls.process_condition(query_obj.condition.excludes, True))
|
|
76
|
-
# 处理搜索条件
|
|
77
|
-
if query_obj.search:
|
|
78
|
-
or_conditions = []
|
|
79
|
-
for sea in query_obj.search:
|
|
80
|
-
search_query = {}
|
|
81
|
-
search_query.update(cls.process_condition(sea.includes))
|
|
82
|
-
search_query.update(cls.process_condition(sea.excludes, True))
|
|
83
|
-
if search_query:
|
|
84
|
-
or_conditions.append(search_query)
|
|
85
|
-
if or_conditions:
|
|
86
|
-
query["$or"] = or_conditions
|
|
87
|
-
# 处理和合并finder条件
|
|
88
|
-
finder_query = cls.process_finder(query_obj.finder)
|
|
89
|
-
if finder_query and query:
|
|
90
|
-
return {"$and": [query, finder_query]}
|
|
91
|
-
return finder_query or query
|
valar/data/orm/__init__.py
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
from django.apps import apps
|
|
3
|
-
from django.core.paginator import Paginator
|
|
4
|
-
from django.db.models import Manager, QuerySet, FileField
|
|
5
|
-
|
|
6
|
-
from .meta_frame import load_meta_frame
|
|
7
|
-
from ..file import minio_remove_path
|
|
8
|
-
from ..orm.detacher import detach_props, save_detached
|
|
9
|
-
from ..orm.meta_loader import load_meta, load_view, load_meta_field
|
|
10
|
-
from ..models import VModel, VTree
|
|
11
|
-
from ..query import Query
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
load_meta_frame()
|
|
15
|
-
|
|
16
|
-
def load_model(entity=None):
|
|
17
|
-
mapping = {}
|
|
18
|
-
for mod in apps.get_models():
|
|
19
|
-
if issubclass(mod, VModel):
|
|
20
|
-
path, name = mod.__module__, mod.__name__
|
|
21
|
-
__old = 'src.valar.' if path.startswith('src') else 'valar.'
|
|
22
|
-
app = path.replace('.models', '').replace(__old,'')
|
|
23
|
-
key = '%s.%s' % (app, name)
|
|
24
|
-
verbose_name = mod._meta.verbose_name
|
|
25
|
-
mapping[key] = [mod, verbose_name]
|
|
26
|
-
return mapping.get(entity) if entity else mapping
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class OrmDao:
|
|
32
|
-
def __init__(self, entity):
|
|
33
|
-
self.entity = entity
|
|
34
|
-
param = load_model(entity)
|
|
35
|
-
if param is None:
|
|
36
|
-
raise Exception('no entity named %s' % entity)
|
|
37
|
-
self.model = param[0]
|
|
38
|
-
self.isTree = issubclass(self.model, VTree)
|
|
39
|
-
self.name: str = param[1]
|
|
40
|
-
self.manager: Manager = self.model.objects
|
|
41
|
-
self.meta_fields = {}
|
|
42
|
-
self.model_fields = {}
|
|
43
|
-
for field in self.model._meta.get_fields():
|
|
44
|
-
_field = load_meta_field(field, self.isTree)
|
|
45
|
-
prop = _field['prop']
|
|
46
|
-
self.model_fields[prop] = field
|
|
47
|
-
self.meta_fields[prop] = _field
|
|
48
|
-
|
|
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
|
-
|
|
82
|
-
def save_one(self, item):
|
|
83
|
-
_item = detach_props(item, self.meta_fields.values())
|
|
84
|
-
_id = item.get('id',0)
|
|
85
|
-
query_set = self.manager.filter(id=_id)
|
|
86
|
-
if len(query_set):
|
|
87
|
-
del item['id']
|
|
88
|
-
item['modify_time'] = datetime.datetime.now()
|
|
89
|
-
self.__check_remove_file__(query_set,item)
|
|
90
|
-
query_set.update(**item)
|
|
91
|
-
bean = query_set.first()
|
|
92
|
-
else:
|
|
93
|
-
bean = self.manager.create(**item)
|
|
94
|
-
bean.sort = bean.id
|
|
95
|
-
bean.save()
|
|
96
|
-
save_detached(bean, _item, self.model_fields)
|
|
97
|
-
return bean
|
|
98
|
-
|
|
99
|
-
def update_many(self, query: Query, template):
|
|
100
|
-
query_set, total = self.find_many(query)
|
|
101
|
-
query_set.update(**template)
|
|
102
|
-
|
|
103
|
-
def delete_one(self, _id):
|
|
104
|
-
query_set = self.manager.filter(id=_id)
|
|
105
|
-
self.__check_remove_file__(query_set)
|
|
106
|
-
query_set.delete()
|
|
107
|
-
|
|
108
|
-
def delete_many(self, query: Query):
|
|
109
|
-
query_set, total = self.find_many(query)
|
|
110
|
-
self.__check_remove_file__(query_set)
|
|
111
|
-
query_set.delete()
|
|
112
|
-
|
|
113
|
-
def find_one(self, _id):
|
|
114
|
-
return self.manager.filter(id=_id).first()
|
|
115
|
-
|
|
116
|
-
def find_many(self, query: Query, size=0, page=1):
|
|
117
|
-
includes, excludes = query.orm_conditions()
|
|
118
|
-
query_set = self.manager.filter(includes).exclude(excludes).order_by(*query.orm_orders())
|
|
119
|
-
total = query_set.count()
|
|
120
|
-
if size:
|
|
121
|
-
paginator = Paginator(query_set, size)
|
|
122
|
-
query_set = paginator.page(page).object_list
|
|
123
|
-
return query_set, total
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def meta(self, code:str = 'default'):
|
|
127
|
-
omit = [ 'id', 'saved', 'sort', 'create_time', 'modify_time']
|
|
128
|
-
fields = [ self.meta_fields[prop] for prop in self.meta_fields if prop not in omit]
|
|
129
|
-
view = load_view(self.entity, code, self.name, fields)
|
|
130
|
-
_view = load_meta(view)
|
|
131
|
-
_view['isTree'] = self.isTree
|
|
132
|
-
return _view
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
valar/data/orm/detacher.py
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
from django.db.models import (ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, CharField,
|
|
2
|
-
OneToOneRel, IntegerField, BooleanField, FloatField, FileField, JSONField, DateField,
|
|
3
|
-
DateTimeField, TimeField, QuerySet)
|
|
4
|
-
|
|
5
|
-
from ..models import VModel
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def detach_props(item, fields):
|
|
9
|
-
keys = [field['prop'] for field in fields if
|
|
10
|
-
field['domain'] in ['ManyToOneRel', 'ManyToManyField', 'ManyToManyRel', 'OneToOneRel', 'OneToOneField']]
|
|
11
|
-
_item = {}
|
|
12
|
-
for key in keys:
|
|
13
|
-
value = item.get(key)
|
|
14
|
-
if value is not None:
|
|
15
|
-
_item[key] = value
|
|
16
|
-
del item[key]
|
|
17
|
-
return _item
|
|
18
|
-
|
|
19
|
-
def save_detached(bean, _item, model_fields ):
|
|
20
|
-
for prop in _item:
|
|
21
|
-
value = _item[prop]
|
|
22
|
-
field = model_fields.get(prop)
|
|
23
|
-
clazz = type(field)
|
|
24
|
-
if clazz == ManyToManyField:
|
|
25
|
-
m2m = getattr(bean, prop)
|
|
26
|
-
m2m.clear()
|
|
27
|
-
m2m.add(*value)
|
|
28
|
-
elif clazz == ManyToOneRel:
|
|
29
|
-
getattr(bean, field.get_accessor_name()).clear()
|
|
30
|
-
remote_model: VModel = field.related_model
|
|
31
|
-
new_set: QuerySet = remote_model.objects.filter(id__in=value)
|
|
32
|
-
remote_field: ForeignKey = field.remote_field
|
|
33
|
-
k = remote_field.get_attname()
|
|
34
|
-
new_set.update(**{k: bean.id})
|
|
35
|
-
elif clazz == ManyToManyRel:
|
|
36
|
-
getattr(bean, field.get_accessor_name()).clear()
|
|
37
|
-
remote_model: VModel = field.related_model
|
|
38
|
-
remote_items: QuerySet = remote_model.objects.filter(id__in=value)
|
|
39
|
-
remote_field: ManyToManyField = field.remote_field
|
|
40
|
-
remote_field_prop = remote_field.get_attname()
|
|
41
|
-
for _bean in remote_items:
|
|
42
|
-
bean_set = getattr(_bean, remote_field_prop)
|
|
43
|
-
bean_set.add(bean)
|
|
44
|
-
elif clazz == OneToOneRel:
|
|
45
|
-
remote_model: VModel = field.related_model
|
|
46
|
-
remote_field: OneToOneField = field.remote_field
|
|
47
|
-
remote_field_prop = remote_field.get_attname()
|
|
48
|
-
_bean = remote_model.objects.get(id=value)
|
|
49
|
-
__bean = remote_model.objects.filter(**{remote_field_prop: bean.id}).first()
|
|
50
|
-
if __bean:
|
|
51
|
-
setattr(__bean, remote_field_prop, None)
|
|
52
|
-
__bean.save()
|
|
53
|
-
setattr(_bean, remote_field_prop, bean.id)
|
|
54
|
-
_bean.save()
|
|
55
|
-
elif clazz == OneToOneField:
|
|
56
|
-
__bean = field.model.objects.filter(**{prop: value}).first()
|
|
57
|
-
if __bean:
|
|
58
|
-
setattr(__bean, prop, None)
|
|
59
|
-
__bean.save()
|
|
60
|
-
setattr(bean, prop, value)
|
|
61
|
-
bean.save()
|
valar/data/orm/meta.py
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
mf_common = ['prop','name']
|
|
2
|
-
|
|
3
|
-
meta_props = {
|
|
4
|
-
'data.Meta': {
|
|
5
|
-
'default': ('pick', ['entity','name']),
|
|
6
|
-
},
|
|
7
|
-
'data.MetaView': {
|
|
8
|
-
'list': ('pick', ['meta_id','code','view_name']),
|
|
9
|
-
},
|
|
10
|
-
'data.MetaField': {
|
|
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
|
-
'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
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
},
|
|
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
|
-
}
|
|
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
|
-
},
|
|
98
|
-
}
|
|
99
|
-
}
|
valar/data/orm/meta_frame.py
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from django.db import OperationalError
|
|
3
|
-
|
|
4
|
-
from ...data.models import MetaFieldDomain, MetaFieldTool
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def load_meta_frame():
|
|
8
|
-
try:
|
|
9
|
-
MetaFieldTool.objects.all().delete()
|
|
10
|
-
MetaFieldDomain.objects.all().delete()
|
|
11
|
-
for row in meta_field_tool:
|
|
12
|
-
row['saved'] = True
|
|
13
|
-
MetaFieldTool.objects.create(**row)
|
|
14
|
-
for row in meta_field_domain:
|
|
15
|
-
row['saved'] = True
|
|
16
|
-
tools = row.get('tools', '').split(';')
|
|
17
|
-
del row['tools']
|
|
18
|
-
item = MetaFieldDomain.objects.create(**row)
|
|
19
|
-
for tk in tools:
|
|
20
|
-
item.tools.add(tk)
|
|
21
|
-
except OperationalError as e:
|
|
22
|
-
print('initialization')
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def convert_meta_fields(fields, entity):
|
|
26
|
-
values = MetaFieldDomain.objects.all().values('name', 'default__code', 'align')
|
|
27
|
-
mapping = {vs['name']: {
|
|
28
|
-
"tool": vs['default__code'],
|
|
29
|
-
"align": vs['align']
|
|
30
|
-
} for vs in values}
|
|
31
|
-
array = []
|
|
32
|
-
for field in fields:
|
|
33
|
-
node = mapping[field.domain]
|
|
34
|
-
_field = field.json
|
|
35
|
-
if field.tool == 'default':
|
|
36
|
-
_field['tool'] = node['tool']
|
|
37
|
-
_field['align'] = node['align']
|
|
38
|
-
_field['entity'] = entity
|
|
39
|
-
array.append(_field)
|
|
40
|
-
return array
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
meta_field_tool = [
|
|
45
|
-
{'id': 2, 'sort': 32, 'pid': 7, 'isLeaf': True, 'name': '输入框', 'code': 'text'},
|
|
46
|
-
{'id': 3, 'sort': 17, 'pid': 0, 'isLeaf': False, 'name': 'SPEC', 'code': '特殊工具集'},
|
|
47
|
-
{'id': 5, 'sort': 22, 'pid': 0, 'isLeaf': False, 'name': 'DATE', 'code': '日期时间工具集'},
|
|
48
|
-
{'id': 6, 'sort': 21, 'pid': 8, 'isLeaf': True, 'name': '数字输入', 'code': 'number'},
|
|
49
|
-
{'id': 7, 'sort': 36, 'pid': 0, 'isLeaf': False, 'name': 'TEXT', 'code': '文本工具集'},
|
|
50
|
-
{'id': 8, 'sort': 26, 'pid': 0, 'isLeaf': False, 'name': 'NUMB', 'code': '数字工具集'},
|
|
51
|
-
{'id': 9, 'sort': 10, 'pid': 0, 'isLeaf': False, 'name': 'FILE', 'code': '文件工具集'},
|
|
52
|
-
{'id': 10, 'sort': 27, 'pid': 0, 'isLeaf': False, 'name': 'BOOL', 'code': '逻辑工具集'},
|
|
53
|
-
{'id': 11, 'sort': 31, 'pid': 0, 'isLeaf': False, 'name': 'LIST', 'code': '列表工具集'},
|
|
54
|
-
{'id': 12, 'sort': 8, 'pid': 3, 'isLeaf': True, 'name': '对象', 'code': 'object'},
|
|
55
|
-
{'id': 13, 'sort': 5, 'pid': 9, 'isLeaf': True, 'name': '图片上传', 'code': 'image'},
|
|
56
|
-
{'id': 14, 'sort': 2, 'pid': 9, 'isLeaf': True, 'name': '文件上传', 'code': 'file'},
|
|
57
|
-
{'id': 15, 'sort': 13, 'pid': 9, 'isLeaf': True, 'name': '富文本', 'code': 'rich'},
|
|
58
|
-
{'id': 17, 'sort': 11, 'pid': 10, 'isLeaf': True, 'name': '开关', 'code': 'switch'},
|
|
59
|
-
{'id': 18, 'sort': 7, 'pid': 3, 'isLeaf': True, 'name': '元数据', 'code': 'meta'},
|
|
60
|
-
{'id': 19, 'sort': 9, 'pid': 7, 'isLeaf': True, 'name': '颜色选择', 'code': 'color'},
|
|
61
|
-
{'id': 20, 'sort': 14, 'pid': 11, 'isLeaf': True, 'name': '穿梭框', 'code': 'transfer'},
|
|
62
|
-
{'id': 21, 'sort': 16, 'pid': 7, 'isLeaf': True, 'name': '自动填充', 'code': 'auto'},
|
|
63
|
-
{'id': 22, 'sort': 35, 'pid': 5, 'isLeaf': True, 'name': '日期选择', 'code': 'date'},
|
|
64
|
-
{'id': 23, 'sort': 12, 'pid': 10, 'isLeaf': True, 'name': '逻辑选择', 'code': 'boolean'},
|
|
65
|
-
{'id': 24, 'sort': 24, 'pid': 11, 'isLeaf': True, 'name': '列表选择', 'code': 'select'},
|
|
66
|
-
{'id': 25, 'sort': 15, 'pid': 11, 'isLeaf': True, 'name': '树形选择', 'code': 'tree'},
|
|
67
|
-
{'id': 26, 'sort': 23, 'pid': 11, 'isLeaf': True, 'name': '及联选择', 'code': 'cascade'},
|
|
68
|
-
{'id': 27, 'sort': 39, 'pid': 0, 'isLeaf': True, 'name': '默认', 'code': 'default'},
|
|
69
|
-
{'id': 28, 'sort': 25, 'pid': 7, 'isLeaf': True, 'name': '图标', 'code': 'icon'},
|
|
70
|
-
{'id': 31, 'sort': 6, 'pid': 0, 'isLeaf': True, 'name': '无', 'code': 'none'},
|
|
71
|
-
{'id': 32, 'sort': 30, 'pid': 7, 'isLeaf': True, 'name': '文本框', 'code': 'textarea'},
|
|
72
|
-
{'id': 33, 'sort': 18, 'pid': 36, 'isLeaf': True, 'name': '时间区间', 'code': 'timerange'},
|
|
73
|
-
{'id': 35, 'sort': 33, 'pid': 5, 'isLeaf': True, 'name': '时间选择', 'code': 'time'},
|
|
74
|
-
{'id': 36, 'sort': 20, 'pid': 0, 'isLeaf': False, 'name': 'RANGE', 'code': '区间工具集'},
|
|
75
|
-
{'id': 37, 'sort': 38, 'pid': 36, 'isLeaf': True, 'name': '日期区间', 'code': 'daterange'},
|
|
76
|
-
{'id': 39, 'sort': 3, 'pid': 36, 'isLeaf': True, 'name': '多日期', 'code': 'dates'},
|
|
77
|
-
{'id': 54, 'sort': 54, 'pid': 7, 'isLeaf': True, 'name': '集合', 'code': 'set'}
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
meta_field_domain = [
|
|
81
|
-
{'id': 12, 'sort': 22, 'name': 'CharField', 'default_id': 2, 'align': 'left', 'tools': '2;6;18;19;21;22;24;25;26;27;28;31;32;33;37;39;54'},
|
|
82
|
-
{'id': 11, 'sort': 21, 'name': 'TextField', 'default_id': 32, 'align': 'left', 'tools': '2;27;31;32'},
|
|
83
|
-
{'id': 13, 'sort': 20, 'name': 'BooleanField', 'default_id': 17, 'align': 'center', 'tools': '17;23;27;31'},
|
|
84
|
-
{'id': 9, 'sort': 18, 'name': 'IntegerField', 'default_id': 6, 'align': 'right', 'tools': '6;27;31'},
|
|
85
|
-
{'id': 8, 'sort': 16, 'name': 'FloatField', 'default_id': 6, 'align': 'right', 'tools': '6;27;31'},
|
|
86
|
-
{'id': 4, 'sort': 15, 'name': 'ForeignKey', 'default_id': 24, 'align': 'left', 'tools': '24;25;26;27;31'},
|
|
87
|
-
{'id': 2, 'sort': 13, 'name': 'ManyToOneRel', 'default_id': 24, 'align': 'center', 'tools': '20;24;25;26;27;31'},
|
|
88
|
-
{'id': 1, 'sort': 12, 'name': 'ManyToManyField', 'default_id': 24, 'align': 'center', 'tools': '20;24;25;26;27;31'},
|
|
89
|
-
{'id': 22, 'sort': 11, 'name': 'ManyToManyRel', 'default_id': 24, 'align': 'center', 'tools': '20;24;25;26;27;31'},
|
|
90
|
-
{'id': 5, 'sort': 10, 'name': 'OneToOneRel', 'default_id': 31, 'align': 'left', 'tools': '27;31'},
|
|
91
|
-
{'id': 21, 'sort': 9, 'name': 'OneToOneField', 'default_id': 31, 'align': 'left', 'tools': '27;31'},
|
|
92
|
-
{'id': 6, 'sort': 8, 'name': 'DateField', 'default_id': 22, 'align': 'center', 'tools': '22;27;31'},
|
|
93
|
-
{'id': 20, 'sort': 7, 'name': 'TimeField', 'default_id': 35, 'align': 'center', 'tools': '27;31;35'},
|
|
94
|
-
{'id': 7, 'sort': 6, 'name': 'DateTimeField', 'default_id': 22, 'align': 'center', 'tools': '22;27;31'},
|
|
95
|
-
{'id': 3, 'sort': 5, 'name': 'JSONField', 'default_id': 12, 'align': 'center', 'tools': '12;27;31'},
|
|
96
|
-
{'id': 15, 'sort': 4, 'name': 'FileField', 'default_id': 14, 'align': 'center', 'tools': '13;14;15;27;31'},
|
|
97
|
-
{'id': 16, 'sort': 3, 'name': 'BigAutoField', 'default_id': 31, 'align': 'right', 'tools': '27;31'},
|
|
98
|
-
{'id': 18, 'sort': 2, 'name': 'UUIDField', 'default_id': 31, 'align': 'left', 'tools': '27;31'},
|
|
99
|
-
{'id': 10, 'sort': 1, 'name': 'Custom', 'default_id': 31, 'align': 'left', 'tools': '27;31'}
|
|
100
|
-
]
|