valar 1.3.6__tar.gz → 1.3.8__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.3.6/src/valar.egg-info → valar-1.3.8}/PKG-INFO +1 -1
- {valar-1.3.6 → valar-1.3.8}/setup.py +1 -1
- valar-1.3.8/src/valar/auth/Authentication.py +50 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/auth/Middleware.py +10 -6
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/sender.py +5 -4
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/valar_minio.py +6 -4
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/__init__.py +2 -2
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/abstract.py +1 -1
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/engine.py +3 -3
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/mon_dao.py +1 -1
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/orm_dao.py +83 -59
- valar-1.3.8/src/valar/migrations/0001_initial.py +301 -0
- valar-1.3.8/src/valar/migrations/0002_indicatortree.py +34 -0
- valar-1.3.8/src/valar/migrations/0003_remove_indicatortree_frequency_and_more.py +46 -0
- valar-1.3.8/src/valar/migrations/0004_delete_indicatortree.py +16 -0
- valar-1.3.8/src/valar/migrations/0005_indicatortree_indicatorset.py +54 -0
- valar-1.3.8/src/valar/migrations/0006_alter_indicatorset_unique_together_and_more.py +21 -0
- valar-1.3.8/src/valar/migrations/0007_indicatorset_file_indicatorset_unit.py +23 -0
- valar-1.3.8/src/valar/migrations/0008_indicatorset_object_id_alter_indicatorset_unit.py +23 -0
- valar-1.3.8/src/valar/migrations/0009_alter_indicatorset_object_id.py +18 -0
- valar-1.3.8/src/valar/models/__init__.py +1 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/models/auth.py +1 -0
- valar-1.3.8/src/valar/models/indicator.py +24 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/models/meta.py +5 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/auth.py +7 -7
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/file.py +1 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/rest.py +5 -3
- {valar-1.3.6 → valar-1.3.8/src/valar.egg-info}/PKG-INFO +1 -1
- {valar-1.3.6 → valar-1.3.8}/src/valar.egg-info/SOURCES.txt +10 -0
- valar-1.3.6/src/valar/auth/Authentication.py +0 -32
- valar-1.3.6/src/valar/models/__init__.py +0 -1
- {valar-1.3.6 → valar-1.3.8}/LICENSE +0 -0
- {valar-1.3.6 → valar-1.3.8}/README.md +0 -0
- {valar-1.3.6 → valar-1.3.8}/setup.cfg +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/apps.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/auth/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/consumer.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/counter.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/executer.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/mapping.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/channels/views.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/app_mixins/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/app_mixins/auto_migration_mixin.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/app_mixins/auto_urlpatterns_mixin.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/singleton_meta.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/classes/valar_response.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/defaults/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/defaults/field_keys_default.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/defaults/field_values_default.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/defaults/view_defaults.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/frame.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/meta.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/mon_field.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/orm_field.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/dao/query.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/migrations/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/models/core.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/models/frame.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/models/test.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/urls.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/__init__.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/handler.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/meta.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar/views/password.py +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar.egg-info/dependency_links.txt +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar.egg-info/requires.txt +0 -0
- {valar-1.3.6 → valar-1.3.8}/src/valar.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import jwt
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
|
|
4
|
+
from ..classes.valar_response import ValarResponse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ValaAuthError(Exception):
|
|
8
|
+
def __init__(self, message, code):
|
|
9
|
+
self.code = code
|
|
10
|
+
self.message = message
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def auth_required(view_func):
|
|
14
|
+
def wrapper(request, *args, **kwargs):
|
|
15
|
+
try:
|
|
16
|
+
payload = valid_request_token(request)
|
|
17
|
+
request.user_id = payload["user_id"]
|
|
18
|
+
return view_func(request, *args, **kwargs)
|
|
19
|
+
except ValaAuthError as e:
|
|
20
|
+
return ValarResponse(False, e.message, e.code, status=401)
|
|
21
|
+
|
|
22
|
+
return wrapper
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_token_from_request(request):
|
|
26
|
+
auth_header = request.headers.get("Authorization")
|
|
27
|
+
if auth_header and auth_header.startswith("Bearer "):
|
|
28
|
+
return auth_header.split(" ")[1]
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
status = {
|
|
33
|
+
0: (None, None, None),
|
|
34
|
+
1: ('请登录系统', 'info', 401),
|
|
35
|
+
2: ('状态已过期,请重新登录', 'warning', 401),
|
|
36
|
+
3: ('错误状态,请重新登录', 'error', 401),
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def valid_request_token(request):
|
|
41
|
+
token = get_token_from_request(request)
|
|
42
|
+
if not token: raise ValaAuthError('请登录系统', 'info')
|
|
43
|
+
try:
|
|
44
|
+
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
|
|
45
|
+
payload['token'] = token
|
|
46
|
+
return payload
|
|
47
|
+
except jwt.ExpiredSignatureError:
|
|
48
|
+
raise ValaAuthError('状态已过期,请重新登录', 'warning')
|
|
49
|
+
except jwt.InvalidTokenError:
|
|
50
|
+
raise ValaAuthError('错误状态,请重新登录', 'error')
|
|
@@ -4,25 +4,29 @@ import json
|
|
|
4
4
|
from django.http import HttpRequest
|
|
5
5
|
from django.utils.deprecation import MiddlewareMixin
|
|
6
6
|
|
|
7
|
-
from ..auth.Authentication import
|
|
7
|
+
from ..auth.Authentication import valid_request_token, ValaAuthError
|
|
8
8
|
from ..classes.valar_response import ValarResponse
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ValarMiddleware(MiddlewareMixin):
|
|
12
12
|
@staticmethod
|
|
13
13
|
def process_response(request: HttpRequest, response: ValarResponse):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
payload
|
|
17
|
-
|
|
14
|
+
try:
|
|
15
|
+
payload = valid_request_token(request)
|
|
16
|
+
response["token"] = payload['token'] or '~~~'
|
|
17
|
+
"""此处可以加入数据级别的权限验证"""
|
|
18
|
+
except ValaAuthError as e:
|
|
19
|
+
if request.headers.get("Auth"):
|
|
18
20
|
return ValarResponse(False, '无效权限', 'error', status=403)
|
|
21
|
+
|
|
19
22
|
if type(response) == ValarResponse:
|
|
20
23
|
valar_message, valar_code = response.valar_message, response.valar_code
|
|
21
24
|
data = {
|
|
22
25
|
'payload': json.loads(response.content),
|
|
23
26
|
'message': valar_message,
|
|
24
|
-
'code': valar_code
|
|
27
|
+
'code': valar_code,
|
|
25
28
|
}
|
|
26
29
|
response.content = json.dumps(data, ensure_ascii=False).encode("utf-8")
|
|
27
30
|
response["Content-Type"] = "application/json; charset=utf-8"
|
|
31
|
+
|
|
28
32
|
return response
|
|
@@ -7,7 +7,7 @@ from channels.layers import get_channel_layer
|
|
|
7
7
|
from django.http import HttpRequest
|
|
8
8
|
import threading
|
|
9
9
|
from .consumer import VALAR_CHANNEL_GROUP
|
|
10
|
-
from ..auth.Authentication import
|
|
10
|
+
from ..auth.Authentication import valid_request_token
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Channel:
|
|
@@ -19,6 +19,7 @@ class Channel:
|
|
|
19
19
|
self.auth = body.get('auth')
|
|
20
20
|
self.broadcast = body.get('broadcast')
|
|
21
21
|
self.data = body.get('data')
|
|
22
|
+
self.resolve = body.get('resolve')
|
|
22
23
|
|
|
23
24
|
def to_dict(self, status, payload):
|
|
24
25
|
data = {
|
|
@@ -26,6 +27,7 @@ class Channel:
|
|
|
26
27
|
'url': self.url,
|
|
27
28
|
'auth': self.auth,
|
|
28
29
|
'broadcast': self.broadcast,
|
|
30
|
+
'resolve': self.resolve,
|
|
29
31
|
'timestamp': datetime.now().timestamp()
|
|
30
32
|
}
|
|
31
33
|
if status:
|
|
@@ -55,9 +57,8 @@ class ValarChannelSender(Sender):
|
|
|
55
57
|
self.__lock__ = threading.Lock()
|
|
56
58
|
self.__interval__ = interval
|
|
57
59
|
if self.__channel__.auth:
|
|
58
|
-
payload
|
|
59
|
-
|
|
60
|
-
raise Exception('Unauthorized!')
|
|
60
|
+
payload = valid_request_token(request)
|
|
61
|
+
self.user_id = payload["user_id"]
|
|
61
62
|
|
|
62
63
|
def _run(self):
|
|
63
64
|
while self.__loading__:
|
|
@@ -6,20 +6,22 @@ from urllib3 import BaseHTTPResponse
|
|
|
6
6
|
from ..classes.singleton_meta import SingletonMeta
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class ValarMinio
|
|
9
|
+
class ValarMinio:
|
|
10
10
|
|
|
11
11
|
def __init__(self, client, entity):
|
|
12
12
|
self.client = client
|
|
13
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
14
|
|
|
18
15
|
@staticmethod
|
|
19
16
|
def get_object_name(_id, prop, file_name):
|
|
20
17
|
return f"{_id}-{prop}-{file_name}"
|
|
21
18
|
|
|
22
19
|
def upload(self, object_name, _bytes):
|
|
20
|
+
if not self.client:
|
|
21
|
+
raise Exception('未配置Minio')
|
|
22
|
+
if not self.client.bucket_exists(self.bucket_name):
|
|
23
|
+
self.client.make_bucket(self.bucket_name)
|
|
24
|
+
self.client.set_bucket_policy(self.bucket_name, self.__generate_policy__())
|
|
23
25
|
file_data = BytesIO(_bytes)
|
|
24
26
|
file_size = len(_bytes) # file.siz
|
|
25
27
|
self.client.put_object(
|
|
@@ -17,8 +17,8 @@ class Dao(AbstractDao):
|
|
|
17
17
|
def save_many(self, array: list):
|
|
18
18
|
self.dao.save_many(array)
|
|
19
19
|
|
|
20
|
-
def save_one(self, item
|
|
21
|
-
return self.dao.save_one(item
|
|
20
|
+
def save_one(self, item):
|
|
21
|
+
return self.dao.save_one(item)
|
|
22
22
|
|
|
23
23
|
def delete_one(self, _id):
|
|
24
24
|
return self.dao.delete_one(_id)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import pymongo
|
|
2
1
|
from django.apps import apps
|
|
3
2
|
from django.conf import settings
|
|
4
3
|
from urllib.parse import urlparse
|
|
5
4
|
|
|
6
5
|
from django.core.mail import EmailMessage
|
|
7
6
|
from minio import Minio
|
|
7
|
+
from pymongo import MongoClient
|
|
8
8
|
from pymongo.synchronous.collection import Collection
|
|
9
9
|
|
|
10
10
|
from ..classes.singleton_meta import SingletonMeta
|
|
@@ -26,7 +26,7 @@ class ValarEngine(metaclass=SingletonMeta):
|
|
|
26
26
|
|
|
27
27
|
# mon
|
|
28
28
|
if hasattr(settings, 'MONGO_URI'):
|
|
29
|
-
self.mongo_client =
|
|
29
|
+
self.mongo_client: MongoClient = MongoClient(
|
|
30
30
|
settings.MONGO_URI,
|
|
31
31
|
**{
|
|
32
32
|
'maxPoolSize': 10,
|
|
@@ -39,7 +39,7 @@ class ValarEngine(metaclass=SingletonMeta):
|
|
|
39
39
|
)
|
|
40
40
|
self.mongo_engine = self.mongo_client[settings.BASE_APP]
|
|
41
41
|
else:
|
|
42
|
-
self.mongo_client = None
|
|
42
|
+
self.mongo_client: MongoClient = None
|
|
43
43
|
self.mongo_engine = None
|
|
44
44
|
|
|
45
45
|
# minio
|
|
@@ -57,7 +57,7 @@ class MonDao(AbstractDao):
|
|
|
57
57
|
def values(self, conditions, props):
|
|
58
58
|
return None
|
|
59
59
|
|
|
60
|
-
def save_one(self, item
|
|
60
|
+
def save_one(self, item):
|
|
61
61
|
oid, item = self.__detach_item__(item)
|
|
62
62
|
if oid:
|
|
63
63
|
self.manager.update_one({'_id': oid}, {'$set': item})
|
|
@@ -2,16 +2,19 @@ import datetime
|
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
4
|
from django.core.paginator import Paginator
|
|
5
|
+
from django.db.models.options import Options
|
|
5
6
|
|
|
6
7
|
from .abstract import AbstractDao
|
|
7
8
|
from .query import Query
|
|
8
|
-
from django.db.models import ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, OneToOneRel
|
|
9
|
+
from django.db.models import ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, OneToOneRel, \
|
|
10
|
+
CharField, BooleanField, FloatField, IntegerField, BigAutoField
|
|
9
11
|
from django.db.models import QuerySet
|
|
10
12
|
from django.db.models import Manager
|
|
11
13
|
from django.db.models.fields.files import FieldFile
|
|
12
14
|
from django.forms import FileField
|
|
13
15
|
|
|
14
16
|
from ..dao.orm_field import OrmField
|
|
17
|
+
from ..models.auth import Account
|
|
15
18
|
from ..models.core import VTree, VModel
|
|
16
19
|
from ..models.meta import MetaField
|
|
17
20
|
|
|
@@ -35,7 +38,9 @@ class OrmDao(AbstractDao):
|
|
|
35
38
|
self.fields = fields
|
|
36
39
|
|
|
37
40
|
def save_many(self, array: list):
|
|
38
|
-
|
|
41
|
+
for item in array:
|
|
42
|
+
item.update({'saved': True})
|
|
43
|
+
self.save_one(item)
|
|
39
44
|
|
|
40
45
|
def values(self, conditions, props: list):
|
|
41
46
|
query_set, _ = self.find(conditions)
|
|
@@ -43,7 +48,7 @@ class OrmDao(AbstractDao):
|
|
|
43
48
|
props.append('id')
|
|
44
49
|
return list(query_set.values(*props))
|
|
45
50
|
|
|
46
|
-
def save_one(self, item
|
|
51
|
+
def save_one(self, item):
|
|
47
52
|
oid, simple_item, complex_item = self.__detach_item__(item)
|
|
48
53
|
query_set = self.manager.filter(id=oid) if oid else []
|
|
49
54
|
if len(query_set):
|
|
@@ -150,12 +155,13 @@ class OrmDao(AbstractDao):
|
|
|
150
155
|
m2m.clear()
|
|
151
156
|
m2m.add(*value)
|
|
152
157
|
elif clazz == ManyToOneRel:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
pass
|
|
159
|
+
# getattr(bean, model_field.get_accessor_name()).clear()
|
|
160
|
+
# remote_model: VModel = model_field.related_model
|
|
161
|
+
# new_set: QuerySet = remote_model.objects.filter(id__in=value)
|
|
162
|
+
# remote_field: ForeignKey = model_field.remote_field
|
|
163
|
+
# k = remote_field.get_attname()
|
|
164
|
+
# new_set.update(**{k: bean.id})
|
|
159
165
|
elif clazz == ManyToManyRel:
|
|
160
166
|
getattr(bean, model_field.get_accessor_name()).clear()
|
|
161
167
|
remote_model: VModel = model_field.related_model
|
|
@@ -207,6 +213,7 @@ class OrmDao(AbstractDao):
|
|
|
207
213
|
# 简单字段取值
|
|
208
214
|
simple_props = [field.prop for field in meta_fields if field.domain not in __referred_domains__]
|
|
209
215
|
custom_props = __get_custom_props__(self.entity, code)
|
|
216
|
+
|
|
210
217
|
results = list(query_set.filter().values(*[*simple_props, *custom_props]))
|
|
211
218
|
__set_simple_values__(meta_fields, results)
|
|
212
219
|
# 关系型字段取值
|
|
@@ -216,9 +223,72 @@ class OrmDao(AbstractDao):
|
|
|
216
223
|
for meta_field in referred_fields:
|
|
217
224
|
manager: Manager = query_set.model.objects
|
|
218
225
|
qs = manager.filter(id__in=pks)
|
|
219
|
-
__linkage__(meta_field, qs, mapping)
|
|
226
|
+
self.__linkage__(meta_field, qs, mapping)
|
|
220
227
|
return results
|
|
221
228
|
|
|
229
|
+
def __linkage__(self, meta_field: OrmField, query_set: QuerySet, mapping):
|
|
230
|
+
model_field = meta_field.model_field
|
|
231
|
+
prop = model_field.name
|
|
232
|
+
multiple = meta_field.domain in __multiple_domains__
|
|
233
|
+
|
|
234
|
+
# 获取级联关系的键索引
|
|
235
|
+
ref_prop = f'{prop}__id'
|
|
236
|
+
edges = query_set.exclude(**{f'{ref_prop}__isnull': True}).values('id', ref_prop)
|
|
237
|
+
if multiple:
|
|
238
|
+
related_primary_keys = set()
|
|
239
|
+
results_mapping = {}
|
|
240
|
+
for edge in edges:
|
|
241
|
+
_id, rid = edge['id'], edge[ref_prop]
|
|
242
|
+
related_primary_keys.add(rid)
|
|
243
|
+
array = results_mapping.get(_id, [])
|
|
244
|
+
array.append(rid)
|
|
245
|
+
results_mapping[_id] = array
|
|
246
|
+
else:
|
|
247
|
+
results_mapping = {row['id']: row[ref_prop] for row in edges if row[ref_prop]}
|
|
248
|
+
related_primary_keys = set(results_mapping.values())
|
|
249
|
+
|
|
250
|
+
# 获取级联关系从属方的数据
|
|
251
|
+
related_model = model_field.related_model
|
|
252
|
+
related_fields = related_model._meta.get_fields()
|
|
253
|
+
related_props = self.__get_related_props__(related_fields)
|
|
254
|
+
related_values = list(related_model.objects.filter(id__in=related_primary_keys).values(*related_props))
|
|
255
|
+
__set_simple_values__(related_fields, related_values)
|
|
256
|
+
related_mapping = {item['id']: item for item in related_values}
|
|
257
|
+
|
|
258
|
+
# 将从属方的数据绑定在主数据上
|
|
259
|
+
for _id in mapping:
|
|
260
|
+
row = mapping[_id]
|
|
261
|
+
if multiple:
|
|
262
|
+
keys = results_mapping.get(_id, [])
|
|
263
|
+
items = [related_mapping[pid] for pid in keys]
|
|
264
|
+
row[prop] = keys
|
|
265
|
+
row[f'{prop}_set'] = items
|
|
266
|
+
else:
|
|
267
|
+
key = results_mapping.get(_id)
|
|
268
|
+
item = related_mapping.get(key) if key else None
|
|
269
|
+
row[prop] = item
|
|
270
|
+
row[f'{prop}_id'] = key
|
|
271
|
+
|
|
272
|
+
def __get_related_props__(self, fields):
|
|
273
|
+
array = []
|
|
274
|
+
for field in fields:
|
|
275
|
+
domain = type(field).__name__
|
|
276
|
+
prop = field.name
|
|
277
|
+
if field.name in __omit_field_props__ or domain in __multiple_domains__:
|
|
278
|
+
continue
|
|
279
|
+
if domain in __referred_domains__:
|
|
280
|
+
field: ForeignKey = field
|
|
281
|
+
model = field.related_model
|
|
282
|
+
meta: Options = model._meta
|
|
283
|
+
if meta.label != self.entity and meta.label != 'valar.Account':
|
|
284
|
+
_fields = meta.get_fields()
|
|
285
|
+
for _field in _fields:
|
|
286
|
+
if type(_field) in [CharField, BooleanField, FloatField, IntegerField, BigAutoField]:
|
|
287
|
+
array.append(f'{prop}__{_field.name}')
|
|
288
|
+
else:
|
|
289
|
+
array.append(prop)
|
|
290
|
+
return array
|
|
291
|
+
|
|
222
292
|
|
|
223
293
|
""" 以下为静态方法和变量 """
|
|
224
294
|
|
|
@@ -254,52 +324,6 @@ def __set_simple_values__(fields, values):
|
|
|
254
324
|
for prop in json_props:
|
|
255
325
|
row[prop] = json.loads(row[prop]) if type(row[prop]) is str else row[prop]
|
|
256
326
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return [field.name for field in fields if fun(field)]
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def __linkage__(meta_field: OrmField, query_set: QuerySet, mapping):
|
|
265
|
-
model_field = meta_field.model_field
|
|
266
|
-
prop = model_field.name
|
|
267
|
-
multiple = meta_field.domain in __multiple_domains__
|
|
268
|
-
|
|
269
|
-
# 获取级联关系的键索引
|
|
270
|
-
ref_prop = f'{prop}__id'
|
|
271
|
-
edges = query_set.exclude(**{f'{ref_prop}__isnull': True}).values('id', ref_prop)
|
|
272
|
-
if multiple:
|
|
273
|
-
related_primary_keys = set()
|
|
274
|
-
results_mapping = {}
|
|
275
|
-
for edge in edges:
|
|
276
|
-
_id, rid = edge['id'], edge[ref_prop]
|
|
277
|
-
related_primary_keys.add(rid)
|
|
278
|
-
array = results_mapping.get(_id, [])
|
|
279
|
-
array.append(rid)
|
|
280
|
-
results_mapping[_id] = array
|
|
281
|
-
else:
|
|
282
|
-
results_mapping = {row['id']: row[ref_prop] for row in edges if row[ref_prop]}
|
|
283
|
-
related_primary_keys = set(results_mapping.values())
|
|
284
|
-
|
|
285
|
-
# 获取级联关系从属方的数据
|
|
286
|
-
related_model = model_field.related_model
|
|
287
|
-
related_fields = related_model._meta.get_fields()
|
|
288
|
-
related_props = __get_related_props__(related_fields)
|
|
289
|
-
related_values = list(related_model.objects.filter(id__in=related_primary_keys).values(*related_props))
|
|
290
|
-
__set_simple_values__(related_fields, related_values)
|
|
291
|
-
related_mapping = {item['id']: item for item in related_values}
|
|
292
|
-
|
|
293
|
-
# 将从属方的数据绑定在主数据上
|
|
294
|
-
for _id in mapping:
|
|
295
|
-
row = mapping[_id]
|
|
296
|
-
if multiple:
|
|
297
|
-
keys = results_mapping.get(_id, [])
|
|
298
|
-
items = [related_mapping[pid] for pid in keys]
|
|
299
|
-
row[prop] = keys
|
|
300
|
-
row[f'{prop}_set'] = items
|
|
301
|
-
else:
|
|
302
|
-
key = results_mapping.get(_id)
|
|
303
|
-
item = related_mapping.get(key) if key else None
|
|
304
|
-
row[prop] = item
|
|
305
|
-
row[f'{prop}_id'] = key
|
|
327
|
+
# def fun(field): return type(field).__name__ not in __referred_domains__ and field.name not in __omit_field_props__
|
|
328
|
+
#
|
|
329
|
+
# return [field.name for field in fields if fun(field)]
|