valar 1.0.28__py3-none-any.whl → 1.1.0__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.
- migrations/0001_initial.py +141 -0
- models/__init__.py +1 -0
- models/frame.py +30 -0
- valar/data/models.py → models/meta.py +7 -36
- {valar-1.0.28.dist-info → valar-1.1.0.dist-info}/METADATA +1 -1
- valar-1.1.0.dist-info/RECORD +12 -0
- valar-1.1.0.dist-info/top_level.txt +3 -0
- valar/channels/__init__.py +0 -1
- valar/channels/consumer.py +0 -48
- valar/channels/executer.py +0 -13
- valar/channels/mapping.py +0 -21
- valar/channels/sender.py +0 -60
- valar/channels/views.py +0 -12
- valar/core/counter.py +0 -9
- valar/core/dao/__init__.py +0 -0
- valar/core/dao/_mon_array2tree.py +0 -18
- valar/core/dao/dao_base.py +0 -50
- valar/core/dao/dao_mon.py +0 -76
- valar/core/dao/dao_orm.py +0 -96
- valar/core/dao/engine.py +0 -12
- valar/core/dao/engine_minio.py +0 -90
- valar/core/dao/engine_mon.py +0 -34
- valar/core/dao/engine_orm.py +0 -25
- valar/core/dao/model_mon.py +0 -24
- valar/core/dao/model_orm.py +0 -195
- valar/core/dao/query_mon.py +0 -12
- valar/core/dao/query_orm.py +0 -43
- valar/core/dao/utils_orm.py +0 -87
- valar/core/dao_abstract.py +0 -63
- valar/core/meta/__init__.py +0 -0
- valar/core/meta/defaults/__init__.py +0 -0
- valar/core/meta/defaults/field_keys_default.py +0 -17
- valar/core/meta/defaults/field_values_default.py +0 -85
- valar/core/meta/defaults/frame_defaults.py +0 -136
- valar/core/meta/defaults/view_defaults.py +0 -7
- valar/core/meta/field_orm.py +0 -144
- valar/core/meta/init_meta_frame.py +0 -30
- valar/core/meta/meta_orm.py +0 -69
- valar/core/middleware.py +0 -20
- valar/core/response.py +0 -7
- valar/core/singleton_meta.py +0 -6
- valar/data/__init__.py +0 -0
- valar/data/migrations/__init__.py +0 -0
- valar/data/urls.py +0 -18
- valar/data/views/__init__.py +0 -0
- valar/data/views/handler.py +0 -41
- valar/data/views/rest.py +0 -89
- valar-1.0.28.dist-info/RECORD +0 -49
- valar-1.0.28.dist-info/top_level.txt +0 -1
- {valar → frame}/__init__.py +0 -0
- {valar/core → migrations}/__init__.py +0 -0
- /valar/core/valar_models.py → /models/core.py +0 -0
- {valar-1.0.28.dist-info → valar-1.1.0.dist-info}/WHEEL +0 -0
- {valar-1.0.28.dist-info → valar-1.1.0.dist-info}/licenses/LICENSE +0 -0
valar/core/dao/dao_orm.py
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
from django.core.paginator import Paginator
|
|
3
|
-
from django.db.models import QuerySet
|
|
4
|
-
|
|
5
|
-
from .engine import DaoEngine
|
|
6
|
-
from .query_orm import OrmQuery
|
|
7
|
-
from ..dao_abstract import AbstractDao
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class OrmDao(AbstractDao):
|
|
11
|
-
def __init__(self, entity):
|
|
12
|
-
self.entity = entity
|
|
13
|
-
engine = DaoEngine().orm
|
|
14
|
-
self.model = engine.get_model(entity)
|
|
15
|
-
self.objects = self.model.manager
|
|
16
|
-
|
|
17
|
-
def get_model(self):
|
|
18
|
-
return self.model
|
|
19
|
-
|
|
20
|
-
def save_one(self, item):
|
|
21
|
-
oid, simple_item, complex_item = self.model.detach_item(item)
|
|
22
|
-
query_set = self.objects.filter(id=oid) if oid else []
|
|
23
|
-
if len(query_set):
|
|
24
|
-
simple_item['modify_time'] = datetime.datetime.now()
|
|
25
|
-
query_set.update(**simple_item)
|
|
26
|
-
bean = query_set.first()
|
|
27
|
-
else:
|
|
28
|
-
bean = self.objects.create(**simple_item)
|
|
29
|
-
bean.sort = bean.id
|
|
30
|
-
bean.save()
|
|
31
|
-
self.model.save_complex_field(complex_item, bean)
|
|
32
|
-
bean.save()
|
|
33
|
-
return bean
|
|
34
|
-
|
|
35
|
-
def delete_one(self, _id):
|
|
36
|
-
oid = self.model.object_id(_id)
|
|
37
|
-
flag = False
|
|
38
|
-
if oid:
|
|
39
|
-
query_set = self.objects.filter(id=oid)
|
|
40
|
-
self.model.remove_files(query_set)
|
|
41
|
-
query_set.delete()
|
|
42
|
-
flag = True
|
|
43
|
-
return flag
|
|
44
|
-
|
|
45
|
-
def find_one(self, _id):
|
|
46
|
-
oid = self.model.object_id(_id)
|
|
47
|
-
return self.objects.filter(id=oid).first() if oid else None
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def find(self, conditions=None, orders=None,size=0, page=1):
|
|
52
|
-
query = OrmQuery(conditions, orders)
|
|
53
|
-
query_set = self.objects.filter(query.includes).exclude(query.excludes).order_by(*query.orders)
|
|
54
|
-
total = query_set.count()
|
|
55
|
-
if size:
|
|
56
|
-
paginator = Paginator(query_set, size)
|
|
57
|
-
query_set = paginator.page(page).object_list
|
|
58
|
-
return query_set, total
|
|
59
|
-
|
|
60
|
-
def update(self, template, conditions):
|
|
61
|
-
if template and len(template.keys()):
|
|
62
|
-
oid, simple_item, complex_item = self.model.detach_item(template)
|
|
63
|
-
query_set, total = self.find(conditions)
|
|
64
|
-
query_set.update(**simple_item)
|
|
65
|
-
return True
|
|
66
|
-
return False
|
|
67
|
-
|
|
68
|
-
def delete(self, conditions):
|
|
69
|
-
query_set, total = self.find(conditions)
|
|
70
|
-
self.model.remove_files(query_set)
|
|
71
|
-
query_set.delete()
|
|
72
|
-
|
|
73
|
-
def transform(self, o, code=None):
|
|
74
|
-
if isinstance(o, QuerySet):
|
|
75
|
-
return self.model.to_dict(o, code)
|
|
76
|
-
else:
|
|
77
|
-
return o.full()
|
|
78
|
-
|
|
79
|
-
def tree(self, root, conditions=None):
|
|
80
|
-
all_set, _ = self.find([])
|
|
81
|
-
query = OrmQuery(conditions)
|
|
82
|
-
if query.is_empty(conditions):
|
|
83
|
-
return all_set
|
|
84
|
-
values = all_set.values('id', 'pid')
|
|
85
|
-
mapping = {item['id']: item['pid'] for item in values}
|
|
86
|
-
results, _ = self.find(conditions)
|
|
87
|
-
id_set = {root}
|
|
88
|
-
for item in results:
|
|
89
|
-
_id = item.id
|
|
90
|
-
route = []
|
|
91
|
-
while _id is not None:
|
|
92
|
-
route.append(_id)
|
|
93
|
-
_id = mapping.get(_id)
|
|
94
|
-
if root in route:
|
|
95
|
-
id_set.update(route)
|
|
96
|
-
return all_set.filter(id__in=id_set).order_by('-sort')
|
valar/core/dao/engine.py
DELETED
valar/core/dao/engine_minio.py
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import json
|
|
3
|
-
from io import BytesIO
|
|
4
|
-
|
|
5
|
-
from django.conf import settings
|
|
6
|
-
from minio import Minio
|
|
7
|
-
from urllib3 import BaseHTTPResponse
|
|
8
|
-
|
|
9
|
-
from ..singleton_meta import SingletonMeta
|
|
10
|
-
|
|
11
|
-
class MinioEngine(metaclass=SingletonMeta):
|
|
12
|
-
|
|
13
|
-
def __int__(self):
|
|
14
|
-
self.client = Minio(**settings.MINIO_SETTINGS)
|
|
15
|
-
|
|
16
|
-
def __load_bucket__(self, bucket_name):
|
|
17
|
-
if not self.client.bucket_exists(bucket_name):
|
|
18
|
-
self.client.make_bucket(bucket_name)
|
|
19
|
-
policy = __generate_policy__(bucket_name)
|
|
20
|
-
self.client.set_bucket_policy(bucket_name, policy)
|
|
21
|
-
|
|
22
|
-
@staticmethod
|
|
23
|
-
def get_object_name(_id, prop, file_name):
|
|
24
|
-
return f"{_id}-{prop}-{file_name}"
|
|
25
|
-
|
|
26
|
-
@staticmethod
|
|
27
|
-
def get_bucket_name(entity):
|
|
28
|
-
name = f'{settings.BASE_DIR.name}.{entity}'
|
|
29
|
-
return name.replace('_', '-').lower()
|
|
30
|
-
|
|
31
|
-
def upload(self, bucket_name, object_name, _bytes):
|
|
32
|
-
self.__load_bucket__(bucket_name)
|
|
33
|
-
file_data = BytesIO(_bytes)
|
|
34
|
-
file_size = len(_bytes) # file.siz
|
|
35
|
-
self.client.put_object(
|
|
36
|
-
bucket_name=bucket_name,
|
|
37
|
-
object_name=object_name,
|
|
38
|
-
data=file_data,
|
|
39
|
-
length=file_size
|
|
40
|
-
)
|
|
41
|
-
return f'{bucket_name}/{object_name}'
|
|
42
|
-
|
|
43
|
-
def remove_path(self, path):
|
|
44
|
-
bucket_name, object_name = path.split('/')
|
|
45
|
-
self.remove(bucket_name, object_name)
|
|
46
|
-
|
|
47
|
-
def remove(self, bucket_name, object_name):
|
|
48
|
-
self.client.remove_object(
|
|
49
|
-
bucket_name=bucket_name,
|
|
50
|
-
object_name=object_name
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
def read(self, bucket_name, object_name) -> BytesIO:
|
|
54
|
-
ret: BaseHTTPResponse = self.client.get_object(bucket_name=bucket_name, object_name=object_name)
|
|
55
|
-
return BytesIO(ret.read())
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def __generate_policy__(bucket_name):
|
|
59
|
-
return json.dumps({
|
|
60
|
-
"Version": "2012-10-17",
|
|
61
|
-
"Statement": [
|
|
62
|
-
{
|
|
63
|
-
"Sid": "",
|
|
64
|
-
"Effect": "Allow",
|
|
65
|
-
"Principal": {"AWS": "*"},
|
|
66
|
-
"Action": "s3:GetBucketLocation",
|
|
67
|
-
"Resource": f"arn:aws:s3:::{bucket_name}"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"Sid": "",
|
|
71
|
-
"Effect": "Allow",
|
|
72
|
-
"Principal": {"AWS": "*"},
|
|
73
|
-
"Action": "s3:ListBucket",
|
|
74
|
-
"Resource": f"arn:aws:s3:::{bucket_name}"
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"Sid": "",
|
|
78
|
-
"Effect": "Allow",
|
|
79
|
-
"Principal": {"AWS": "*"},
|
|
80
|
-
"Action": "s3:GetObject",
|
|
81
|
-
"Resource": f"arn:aws:s3:::{bucket_name}/*"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"Sid": "",
|
|
85
|
-
"Effect": "Allow",
|
|
86
|
-
"Principal": {"AWS": "*"},
|
|
87
|
-
"Action": "s3:PutObject",
|
|
88
|
-
"Resource": f"arn:aws:s3:::{bucket_name}/*"
|
|
89
|
-
}
|
|
90
|
-
]})
|
valar/core/dao/engine_mon.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import pymongo
|
|
2
|
-
from django.conf import settings
|
|
3
|
-
|
|
4
|
-
from .model_mon import MonModel
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class MonEngine:
|
|
8
|
-
|
|
9
|
-
def __init__(self):
|
|
10
|
-
uri = f'mongodb://localhost:27017/'
|
|
11
|
-
mongo = settings.MONGO
|
|
12
|
-
if mongo:
|
|
13
|
-
param = ['host', 'port', 'username', 'password']
|
|
14
|
-
host, port, username, password = [mongo.get(p) for p in param]
|
|
15
|
-
uri = f'mongodb://{username}:{password}@{host}:{port}/'
|
|
16
|
-
|
|
17
|
-
client = pymongo.MongoClient(uri, **{
|
|
18
|
-
'maxPoolSize': 10,
|
|
19
|
-
'minPoolSize': 0,
|
|
20
|
-
'maxIdleTimeMS': 10000,
|
|
21
|
-
'connectTimeoutMS': 10000,
|
|
22
|
-
'socketTimeoutMS': 10000,
|
|
23
|
-
'serverSelectionTimeoutMS': 10000,
|
|
24
|
-
})
|
|
25
|
-
database = client[settings.BASE_APP]
|
|
26
|
-
self.uri = uri
|
|
27
|
-
self.client = client
|
|
28
|
-
self.database = database
|
|
29
|
-
|
|
30
|
-
def get_mapping(self):
|
|
31
|
-
return {col['name']: self.database[col['name']] for col in self.database.list_collections()}
|
|
32
|
-
|
|
33
|
-
def get_model(self,entity)->MonModel:
|
|
34
|
-
return MonModel(self.database, entity)
|
valar/core/dao/engine_orm.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from django.apps import apps
|
|
2
|
-
|
|
3
|
-
from .model_orm import OrmModel
|
|
4
|
-
from ..valar_models import VModel
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class OrmEngine:
|
|
8
|
-
|
|
9
|
-
def __init__(self):
|
|
10
|
-
mapping = {}
|
|
11
|
-
for model in apps.get_models():
|
|
12
|
-
if issubclass(model, VModel):
|
|
13
|
-
path, name = model.__module__, model.__name__
|
|
14
|
-
prefix = 'src.valar.' if path.startswith('src') else 'valar.'
|
|
15
|
-
app = path.replace('.models', '').replace(prefix, '')
|
|
16
|
-
entity = '%s.%s' % (app, name)
|
|
17
|
-
mapping[entity] = model
|
|
18
|
-
self.mapping = mapping
|
|
19
|
-
|
|
20
|
-
def get_mapping(self)->dict:
|
|
21
|
-
return self.mapping
|
|
22
|
-
|
|
23
|
-
def get_model(self,entity)->OrmModel:
|
|
24
|
-
mod = self.mapping.get(entity)
|
|
25
|
-
return OrmModel(mod, entity)
|
valar/core/dao/model_mon.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from bson import ObjectId
|
|
2
|
-
from bson.errors import InvalidId
|
|
3
|
-
from pymongo.synchronous.collection import Collection
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class MonModel:
|
|
7
|
-
|
|
8
|
-
def __init__(self, database, entity):
|
|
9
|
-
self.entity = entity
|
|
10
|
-
self.name = entity.replace('.', '_')
|
|
11
|
-
self.manager: Collection = database[self.name]
|
|
12
|
-
|
|
13
|
-
@staticmethod
|
|
14
|
-
def object_id(_id):
|
|
15
|
-
try:
|
|
16
|
-
return ObjectId(_id)
|
|
17
|
-
except(InvalidId, TypeError):
|
|
18
|
-
return None
|
|
19
|
-
|
|
20
|
-
def detach_item(self, item):
|
|
21
|
-
_id = item.get('id')
|
|
22
|
-
if _id:
|
|
23
|
-
del item['id']
|
|
24
|
-
return self.object_id(_id), item
|
valar/core/dao/model_orm.py
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
from deepmerge import always_merger
|
|
2
|
-
from django.db.models import ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, OneToOneRel
|
|
3
|
-
from django.db.models import QuerySet
|
|
4
|
-
from django.db.models import Manager
|
|
5
|
-
from django.db.models.fields.files import FieldFile
|
|
6
|
-
from django.forms import FileField
|
|
7
|
-
|
|
8
|
-
from .engine_minio import MinioEngine
|
|
9
|
-
from .utils_orm import OrmUtils
|
|
10
|
-
from ..meta.defaults.field_keys_default import meta_field_key_defaults
|
|
11
|
-
from ..meta.defaults.field_values_default import meta_field_value_defaults
|
|
12
|
-
from ..meta.field_orm import OrmField
|
|
13
|
-
from ..meta.init_meta_frame import init_meta_frame
|
|
14
|
-
from ..valar_models import VModel, VTree
|
|
15
|
-
from ...data.models import MetaFieldDomain
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class OrmModel:
|
|
19
|
-
|
|
20
|
-
def __init__(self, mod, entity):
|
|
21
|
-
self.entity = entity
|
|
22
|
-
self.model = mod
|
|
23
|
-
meta = getattr(mod, '_meta')
|
|
24
|
-
self.name = meta.verbose_name
|
|
25
|
-
self.is_tree = issubclass(mod, VTree)
|
|
26
|
-
self.manager: Manager = mod.objects
|
|
27
|
-
fields = meta.get_fields()
|
|
28
|
-
mapping = {}
|
|
29
|
-
for f in fields:
|
|
30
|
-
field = OrmField(entity, f, self.is_tree)
|
|
31
|
-
mapping[field.prop] = field
|
|
32
|
-
self.mapping = mapping
|
|
33
|
-
self.minio = MinioEngine()
|
|
34
|
-
self.bucket_name = self.minio.get_bucket_name(entity)
|
|
35
|
-
|
|
36
|
-
@staticmethod
|
|
37
|
-
def object_id(_id):
|
|
38
|
-
return _id if isinstance(_id, int) and _id else None
|
|
39
|
-
|
|
40
|
-
def props(self, domain=None):
|
|
41
|
-
array = []
|
|
42
|
-
for prop in self.mapping:
|
|
43
|
-
field: OrmField = self.mapping[prop]
|
|
44
|
-
if field.domain == domain or domain is None:
|
|
45
|
-
array.append(prop)
|
|
46
|
-
return array
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def meta_frame(self):
|
|
50
|
-
query_set = MetaFieldDomain.objects.all()
|
|
51
|
-
if query_set.count() == 0:
|
|
52
|
-
query_set = init_meta_frame()
|
|
53
|
-
values = query_set.values('name', 'default__code', 'align')
|
|
54
|
-
return {
|
|
55
|
-
vs['name']: {
|
|
56
|
-
"tool": vs['default__code'],
|
|
57
|
-
"align": vs['align'],
|
|
58
|
-
}
|
|
59
|
-
for vs in values
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def initial_fields(self, code):
|
|
66
|
-
props = self.props()
|
|
67
|
-
default_keys = meta_field_key_defaults.get(self.entity,{})
|
|
68
|
-
method, array = default_keys.get(code, ('omit',[]))
|
|
69
|
-
def fun(prop): return prop not in array if method == 'omit' else prop in array
|
|
70
|
-
props = [prop for prop in props if fun(prop)]
|
|
71
|
-
|
|
72
|
-
default_values = meta_field_value_defaults.get(self.entity, {})
|
|
73
|
-
init_values = default_values.get('__init__', {})
|
|
74
|
-
code_values = default_values.get(code, {})
|
|
75
|
-
default_fields = always_merger.merge(init_values, code_values)
|
|
76
|
-
|
|
77
|
-
meta_frame = self.meta_frame()
|
|
78
|
-
fields = []
|
|
79
|
-
for prop in props:
|
|
80
|
-
field = self.get_field(prop)
|
|
81
|
-
field_json = field.json()
|
|
82
|
-
frame = meta_frame.get(field.domain, {})
|
|
83
|
-
field_json.update(frame)
|
|
84
|
-
default_field = default_fields.get(prop, {})
|
|
85
|
-
always_merger.merge(field_json, default_field)
|
|
86
|
-
fields.append(field_json)
|
|
87
|
-
|
|
88
|
-
fields.reverse()
|
|
89
|
-
return fields
|
|
90
|
-
|
|
91
|
-
def get_field(self, prop)->OrmField:
|
|
92
|
-
return self.mapping[prop]
|
|
93
|
-
|
|
94
|
-
def detach_item(self, item):
|
|
95
|
-
_id = item.get('id')
|
|
96
|
-
if _id:
|
|
97
|
-
del item['id']
|
|
98
|
-
simple_item = {}
|
|
99
|
-
complex_item = {}
|
|
100
|
-
for prop in item:
|
|
101
|
-
field = self.get_field(prop)
|
|
102
|
-
value = item.get(prop)
|
|
103
|
-
if field.domain in ['ManyToOneRel', 'ManyToManyField', 'ManyToManyRel', 'OneToOneRel', 'OneToOneField','FileField']:
|
|
104
|
-
complex_item[prop] = value
|
|
105
|
-
else:
|
|
106
|
-
simple_item[prop] = value
|
|
107
|
-
return self.object_id(_id), simple_item, complex_item
|
|
108
|
-
|
|
109
|
-
def get_file_paths(self, query_set: QuerySet):
|
|
110
|
-
props = self.props('FileField')
|
|
111
|
-
items = query_set.values(*props)
|
|
112
|
-
array = []
|
|
113
|
-
for item in items:
|
|
114
|
-
array += [i for i in item.values() if i]
|
|
115
|
-
return array
|
|
116
|
-
|
|
117
|
-
def remove_files(self, query_set: QuerySet):
|
|
118
|
-
paths = self.get_file_paths(query_set)
|
|
119
|
-
for path in paths:
|
|
120
|
-
self.minio.remove_path(path)
|
|
121
|
-
|
|
122
|
-
def save_complex_field(self, complex_item, bean):
|
|
123
|
-
for prop in complex_item:
|
|
124
|
-
value = complex_item[prop]
|
|
125
|
-
field = self.get_field(prop).model_field
|
|
126
|
-
clazz = type(field)
|
|
127
|
-
if clazz == ManyToManyField:
|
|
128
|
-
m2m = getattr(bean, prop)
|
|
129
|
-
m2m.clear()
|
|
130
|
-
m2m.add(*value)
|
|
131
|
-
elif clazz == ManyToOneRel:
|
|
132
|
-
getattr(bean, field.get_accessor_name()).clear()
|
|
133
|
-
remote_model: VModel = field.related_model
|
|
134
|
-
new_set: QuerySet = remote_model.objects.filter(id__in=value)
|
|
135
|
-
remote_field: ForeignKey = field.remote_field
|
|
136
|
-
k = remote_field.get_attname()
|
|
137
|
-
new_set.update(**{k: bean.id})
|
|
138
|
-
elif clazz == ManyToManyRel:
|
|
139
|
-
getattr(bean, field.get_accessor_name()).clear()
|
|
140
|
-
remote_model: VModel = field.related_model
|
|
141
|
-
remote_items: QuerySet = remote_model.objects.filter(id__in=value)
|
|
142
|
-
remote_field: ManyToManyField = field.remote_field
|
|
143
|
-
remote_field_prop = remote_field.get_attname()
|
|
144
|
-
for _bean in remote_items:
|
|
145
|
-
bean_set = getattr(_bean, remote_field_prop)
|
|
146
|
-
bean_set.add(bean)
|
|
147
|
-
elif clazz == OneToOneRel:
|
|
148
|
-
remote_model: VModel = field.related_model
|
|
149
|
-
remote_field: OneToOneField = field.remote_field
|
|
150
|
-
remote_field_prop = remote_field.get_attname()
|
|
151
|
-
_bean = remote_model.objects.get(id=value)
|
|
152
|
-
__bean = remote_model.objects.filter(**{remote_field_prop: bean.id}).first()
|
|
153
|
-
if __bean:
|
|
154
|
-
setattr(__bean, remote_field_prop, None)
|
|
155
|
-
__bean.save()
|
|
156
|
-
setattr(_bean, remote_field_prop, bean.id)
|
|
157
|
-
_bean.save()
|
|
158
|
-
elif clazz == OneToOneField:
|
|
159
|
-
__bean = field.model.objects.filter(**{prop: value}).first()
|
|
160
|
-
if __bean:
|
|
161
|
-
setattr(__bean, prop, None)
|
|
162
|
-
__bean.save()
|
|
163
|
-
setattr(bean, prop, value)
|
|
164
|
-
elif clazz == FileField:
|
|
165
|
-
file_name, _bytes = value
|
|
166
|
-
field_file: FieldFile = getattr(bean, prop)
|
|
167
|
-
if field_file:
|
|
168
|
-
path = field_file.name
|
|
169
|
-
self.minio.remove_path(path)
|
|
170
|
-
object_name = self.minio.get_object_name(bean.id, prop, file_name)
|
|
171
|
-
path = self.minio.upload(self.bucket_name, object_name, _bytes) if _bytes else None
|
|
172
|
-
setattr(bean, prop, path)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def to_dict(self, query_set: QuerySet, code=None):
|
|
178
|
-
# query_set = query_set.filter(saved=True)
|
|
179
|
-
utils = OrmUtils()
|
|
180
|
-
orm_fields = self.mapping.values()
|
|
181
|
-
# 简单字段取值
|
|
182
|
-
simple_props = [field.prop for field in orm_fields if field.domain not in utils.referred_domains]
|
|
183
|
-
custom_props = utils.custom_props(self.entity, code)
|
|
184
|
-
results = list(query_set.filter().values(*[*simple_props, *custom_props]))
|
|
185
|
-
utils.date_values(orm_fields, results)
|
|
186
|
-
# 关系型字段取值
|
|
187
|
-
mapping = { row['id']: row for row in results}
|
|
188
|
-
referred_fields = [field for field in orm_fields if field.domain in utils.referred_domains]
|
|
189
|
-
pks = mapping.keys()
|
|
190
|
-
for field in referred_fields:
|
|
191
|
-
manager: Manager = query_set.model.objects
|
|
192
|
-
qs = manager.filter(id__in=pks)
|
|
193
|
-
utils.linkage(field, qs, mapping)
|
|
194
|
-
return results
|
|
195
|
-
|
valar/core/dao/query_mon.py
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
def __translate_finder__(conditions):
|
|
3
|
-
return {}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class MonQuery:
|
|
7
|
-
|
|
8
|
-
def __init__(self, conditions: list, orders = None):
|
|
9
|
-
self.orders = orders or {'sort': -1}
|
|
10
|
-
conditions = conditions if len(conditions) else [{'includes':{},'excludes':{}}]
|
|
11
|
-
self.finder = __translate_finder__(conditions)
|
|
12
|
-
|
valar/core/dao/query_orm.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
from django.db.models import Q
|
|
2
|
-
from functools import reduce
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def __fun__(x, y): return x | y
|
|
7
|
-
def __translate_orders__(orders):
|
|
8
|
-
array = []
|
|
9
|
-
for key in orders:
|
|
10
|
-
value = orders.get(key)
|
|
11
|
-
prefix = '-' if value == -1 else ''
|
|
12
|
-
array.append(f'{prefix}{key}')
|
|
13
|
-
return array
|
|
14
|
-
def __translate_condition__(conditions, _type):
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return reduce(__fun__, [Q(**cond[_type]) for cond in conditions])
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class OrmQuery:
|
|
22
|
-
|
|
23
|
-
def __init__(self, conditions: list, orders = None):
|
|
24
|
-
self.orders = __translate_orders__(orders or {'sort': -1})
|
|
25
|
-
conditions = conditions if len(conditions) else [{'includes':{},'excludes':{}}]
|
|
26
|
-
self.includes = __translate_condition__(conditions,'includes')
|
|
27
|
-
self.excludes = __translate_condition__(conditions, 'excludes')
|
|
28
|
-
|
|
29
|
-
@staticmethod
|
|
30
|
-
def is_empty(conditions):
|
|
31
|
-
if conditions and len(conditions):
|
|
32
|
-
temp = {}
|
|
33
|
-
for cond in conditions:
|
|
34
|
-
temp.update(cond)
|
|
35
|
-
return len(temp.keys()) >0
|
|
36
|
-
else:
|
|
37
|
-
return True
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
valar/core/dao/utils_orm.py
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
from django.db.models import QuerySet
|
|
2
|
-
|
|
3
|
-
from ..valar_models import VModel
|
|
4
|
-
from ...core.meta.field_orm import OrmField
|
|
5
|
-
from ...data.models import MetaField
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class OrmUtils:
|
|
9
|
-
def __init__(self):
|
|
10
|
-
self.multiple_domains = ['ManyToOneRel', 'ManyToManyField', 'ManyToManyRel']
|
|
11
|
-
self.referred_domains = [*self.multiple_domains, 'OneToOneRel', 'OneToOneField', 'ForeignKey']
|
|
12
|
-
self.omit_field_props = ['create_time', 'modify_time', 'saved', 'sort']
|
|
13
|
-
self.data_props_formatting = {'DateField': '%Y-%m-%d', 'DateTimeField': '%Y-%m-%d %H:%M:%S', 'TimeField': '%H:%M:%S'}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@staticmethod
|
|
17
|
-
def json(bean: VModel):
|
|
18
|
-
pass
|
|
19
|
-
|
|
20
|
-
@staticmethod
|
|
21
|
-
def custom_props(entity, code='default'):
|
|
22
|
-
field_set = MetaField.objects.filter(view__code=code, view__meta__entity=entity, domain='Custom').values('prop')
|
|
23
|
-
return [item['prop'] for item in field_set if item['prop']]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def linkage(self, field, query_set: QuerySet, mapping):
|
|
27
|
-
model_field = field.model_field
|
|
28
|
-
prop = model_field.name
|
|
29
|
-
multiple = field.domain in self.multiple_domains
|
|
30
|
-
|
|
31
|
-
# 获取级联关系的键索引
|
|
32
|
-
ref_prop = f'{prop}__id'
|
|
33
|
-
edges = query_set.exclude(**{f'{ref_prop}__isnull': True}).values('id', ref_prop)
|
|
34
|
-
if multiple:
|
|
35
|
-
related_primary_keys = set()
|
|
36
|
-
results_mapping = {}
|
|
37
|
-
for edge in edges:
|
|
38
|
-
_id, rid = edge['id'], edge[ref_prop]
|
|
39
|
-
related_primary_keys.add(rid)
|
|
40
|
-
array = results_mapping.get(_id, [])
|
|
41
|
-
array.append(rid)
|
|
42
|
-
results_mapping[_id] = array
|
|
43
|
-
else:
|
|
44
|
-
results_mapping = {row['id']: row[ref_prop] for row in edges if row[ref_prop]}
|
|
45
|
-
related_primary_keys = set(results_mapping.values())
|
|
46
|
-
|
|
47
|
-
# 获取级联关系从属方的数据
|
|
48
|
-
related_model = model_field.related_model
|
|
49
|
-
related_fields = related_model._meta.get_fields()
|
|
50
|
-
related_props = self.__get_related_props__(related_fields)
|
|
51
|
-
related_values = list(related_model.objects.filter(id__in=related_primary_keys).values(*related_props))
|
|
52
|
-
self.date_values(related_fields, related_values)
|
|
53
|
-
related_mapping = {item['id']: item for item in related_values}
|
|
54
|
-
|
|
55
|
-
# 将从属方的数据绑定在主数据上
|
|
56
|
-
for _id in mapping:
|
|
57
|
-
row = mapping[_id]
|
|
58
|
-
if multiple:
|
|
59
|
-
keys = results_mapping.get(_id, [])
|
|
60
|
-
items = [related_mapping[pid] for pid in keys]
|
|
61
|
-
row[prop] = keys
|
|
62
|
-
row[f'{prop}_set'] = items
|
|
63
|
-
else:
|
|
64
|
-
key = results_mapping.get(_id)
|
|
65
|
-
item = related_mapping.get(key) if key else None
|
|
66
|
-
row[prop] = item
|
|
67
|
-
row[f'{prop}_id'] = key
|
|
68
|
-
|
|
69
|
-
def __get_related_props__(self,fields):
|
|
70
|
-
def fun(field): return type(field).__name__ not in self.referred_domains and field.name not in self.omit_field_props
|
|
71
|
-
return [field.name for field in fields if fun(field)]
|
|
72
|
-
|
|
73
|
-
def date_values(self, fields, values):
|
|
74
|
-
date_props_mapping = {}
|
|
75
|
-
for field in fields:
|
|
76
|
-
if isinstance(field, OrmField):
|
|
77
|
-
prop = field.prop
|
|
78
|
-
domain = field.domain
|
|
79
|
-
else:
|
|
80
|
-
prop = field.name
|
|
81
|
-
domain = type(field).__name__
|
|
82
|
-
if domain in self.data_props_formatting.keys():
|
|
83
|
-
date_props_mapping[prop] = self.data_props_formatting[domain]
|
|
84
|
-
for row in values:
|
|
85
|
-
for prop, formating in date_props_mapping.items():
|
|
86
|
-
if row.get(prop):
|
|
87
|
-
row[prop] = row[prop].strftime(formating)
|
valar/core/dao_abstract.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
|
|
3
|
-
class AbstractDao(ABC):
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@abstractmethod
|
|
7
|
-
def get_model(self):
|
|
8
|
-
pass
|
|
9
|
-
|
|
10
|
-
@abstractmethod
|
|
11
|
-
def save_one(self, item):
|
|
12
|
-
pass
|
|
13
|
-
|
|
14
|
-
@abstractmethod
|
|
15
|
-
def delete_one(self, _id):
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
|
-
@abstractmethod
|
|
19
|
-
def find_one(self, _id):
|
|
20
|
-
pass
|
|
21
|
-
|
|
22
|
-
@abstractmethod
|
|
23
|
-
def find(self, conditions=None, orders=None, size=0, page=1):
|
|
24
|
-
pass
|
|
25
|
-
|
|
26
|
-
@abstractmethod
|
|
27
|
-
def update(self, template, conditions):
|
|
28
|
-
pass
|
|
29
|
-
|
|
30
|
-
@abstractmethod
|
|
31
|
-
def delete(self, conditions):
|
|
32
|
-
pass
|
|
33
|
-
|
|
34
|
-
@abstractmethod
|
|
35
|
-
def transform(self, o, code=None):
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
@abstractmethod
|
|
39
|
-
def tree(self, root, conditions=None):
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
def search(self, includes=None, excludes=None, orders=None):
|
|
43
|
-
conditions = [{
|
|
44
|
-
"includes": includes or {},
|
|
45
|
-
"excludes": excludes or {}
|
|
46
|
-
}]
|
|
47
|
-
query_set, _ = self.find(conditions, orders)
|
|
48
|
-
return query_set
|
|
49
|
-
|
|
50
|
-
# @abstractmethod
|
|
51
|
-
# def values(self, props, conditions, orders=None):
|
|
52
|
-
# pass
|
|
53
|
-
#
|
|
54
|
-
# @abstractmethod
|
|
55
|
-
# def group(self, props, conditions, orders=None):
|
|
56
|
-
# pass
|
|
57
|
-
#
|
|
58
|
-
# @abstractmethod
|
|
59
|
-
# def count(self, props, conditions):
|
|
60
|
-
# pass
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
valar/core/meta/__init__.py
DELETED
|
File without changes
|
|
File without changes
|