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.

Files changed (64) hide show
  1. valar/__init__.py +0 -26
  2. valar/channels/__init__.py +1 -107
  3. valar/channels/consumer.py +48 -0
  4. valar/channels/executer.py +13 -0
  5. valar/channels/mapping.py +21 -0
  6. valar/channels/sender.py +60 -0
  7. valar/channels/views.py +6 -11
  8. valar/core/__init__.py +0 -0
  9. valar/core/counter.py +9 -0
  10. valar/core/dao/__init__.py +0 -0
  11. valar/core/dao/_mon_array2tree.py +18 -0
  12. valar/core/dao/dao_base.py +50 -0
  13. valar/core/dao/dao_mon.py +76 -0
  14. valar/core/dao/dao_orm.py +96 -0
  15. valar/core/dao/engine.py +12 -0
  16. valar/core/dao/engine_minio.py +90 -0
  17. valar/core/dao/engine_mon.py +34 -0
  18. valar/core/dao/engine_orm.py +25 -0
  19. valar/core/dao/model_mon.py +24 -0
  20. valar/core/dao/model_orm.py +192 -0
  21. valar/core/dao/query_mon.py +12 -0
  22. valar/core/dao/query_orm.py +43 -0
  23. valar/core/dao/utils_orm.py +85 -0
  24. valar/core/dao_abstract.py +63 -0
  25. valar/core/meta/__init__.py +0 -0
  26. valar/core/meta/defaults/__init__.py +0 -0
  27. valar/core/meta/defaults/field_keys_default.py +17 -0
  28. valar/core/meta/defaults/field_values_default.py +85 -0
  29. valar/core/meta/defaults/frame_defaults.py +136 -0
  30. valar/core/meta/defaults/view_defaults.py +7 -0
  31. valar/core/meta/field_orm.py +144 -0
  32. valar/core/meta/init_meta_frame.py +30 -0
  33. valar/core/meta/meta_orm.py +69 -0
  34. valar/core/middleware.py +20 -0
  35. valar/core/response.py +7 -0
  36. valar/core/singleton_meta.py +6 -0
  37. valar/core/valar_models.py +82 -0
  38. valar/data/apps.py +22 -0
  39. valar/data/migrations/0001_initial.py +141 -0
  40. valar/data/models.py +2 -121
  41. valar/data/urls.py +15 -21
  42. valar/data/views/__init__.py +0 -0
  43. valar/data/views/handler.py +41 -0
  44. valar/data/views/rest.py +86 -0
  45. {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/METADATA +1 -1
  46. valar-1.0.22.dist-info/RECORD +51 -0
  47. {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/WHEEL +1 -1
  48. valar/channels/utils.py +0 -43
  49. valar/data/file/__init__.py +0 -91
  50. valar/data/handlers.py +0 -28
  51. valar/data/mon/__init__.py +0 -123
  52. valar/data/mon/query_translator.py +0 -91
  53. valar/data/orm/__init__.py +0 -135
  54. valar/data/orm/detacher.py +0 -61
  55. valar/data/orm/meta.py +0 -99
  56. valar/data/orm/meta_frame.py +0 -100
  57. valar/data/orm/meta_loader.py +0 -200
  58. valar/data/orm/values.py +0 -102
  59. valar/data/query.py +0 -48
  60. valar/data/utils.py +0 -70
  61. valar/data/views.py +0 -173
  62. valar-1.0.21.dist-info/RECORD +0 -26
  63. {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/licenses/LICENSE +0 -0
  64. {valar-1.0.21.dist-info → valar-1.0.22.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,136 @@
1
+
2
+ meta_field_tool = [
3
+ {'id': 2, 'sort': 32, 'pid': 7, 'isLeaf': True, 'name': '输入框', 'code': 'text'},
4
+ {'id': 3, 'sort': 17, 'pid': 0, 'isLeaf': False, 'name': 'SPEC', 'code': '特殊工具集'},
5
+ {'id': 5, 'sort': 22, 'pid': 0, 'isLeaf': False, 'name': 'DATE', 'code': '日期时间工具集'},
6
+ {'id': 6, 'sort': 21, 'pid': 8, 'isLeaf': True, 'name': '数字输入', 'code': 'number'},
7
+ {'id': 7, 'sort': 36, 'pid': 0, 'isLeaf': False, 'name': 'TEXT', 'code': '文本工具集'},
8
+ {'id': 8, 'sort': 26, 'pid': 0, 'isLeaf': False, 'name': 'NUMB', 'code': '数字工具集'},
9
+ {'id': 9, 'sort': 10, 'pid': 0, 'isLeaf': False, 'name': 'FILE', 'code': '文件工具集'},
10
+ {'id': 10, 'sort': 27, 'pid': 0, 'isLeaf': False, 'name': 'BOOL', 'code': '逻辑工具集'},
11
+ {'id': 11, 'sort': 31, 'pid': 0, 'isLeaf': False, 'name': 'LIST', 'code': '列表工具集'},
12
+ {'id': 12, 'sort': 8, 'pid': 3, 'isLeaf': True, 'name': '对象', 'code': 'object'},
13
+ {'id': 13, 'sort': 5, 'pid': 9, 'isLeaf': True, 'name': '图片上传', 'code': 'image'},
14
+ {'id': 14, 'sort': 2, 'pid': 9, 'isLeaf': True, 'name': '文件上传', 'code': 'file'},
15
+ {'id': 15, 'sort': 13, 'pid': 9, 'isLeaf': True, 'name': '富文本', 'code': 'rich'},
16
+ {'id': 17, 'sort': 11, 'pid': 10, 'isLeaf': True, 'name': '开关', 'code': 'switch'},
17
+ {'id': 18, 'sort': 7, 'pid': 3, 'isLeaf': True, 'name': '元数据', 'code': 'meta'},
18
+ {'id': 19, 'sort': 9, 'pid': 7, 'isLeaf': True, 'name': '颜色选择', 'code': 'color'},
19
+ {'id': 20, 'sort': 14, 'pid': 11, 'isLeaf': True, 'name': '穿梭框', 'code': 'transfer'},
20
+ {'id': 21, 'sort': 16, 'pid': 7, 'isLeaf': True, 'name': '自动填充', 'code': 'auto'},
21
+ {'id': 22, 'sort': 35, 'pid': 5, 'isLeaf': True, 'name': '日期选择', 'code': 'date'},
22
+ {'id': 23, 'sort': 12, 'pid': 10, 'isLeaf': True, 'name': '逻辑选择', 'code': 'boolean'},
23
+ {'id': 24, 'sort': 24, 'pid': 11, 'isLeaf': True, 'name': '列表选择', 'code': 'select'},
24
+ {'id': 25, 'sort': 15, 'pid': 11, 'isLeaf': True, 'name': '树形选择', 'code': 'tree'},
25
+ {'id': 26, 'sort': 23, 'pid': 11, 'isLeaf': True, 'name': '及联选择', 'code': 'cascade'},
26
+ {'id': 28, 'sort': 25, 'pid': 7, 'isLeaf': True, 'name': '图标', 'code': 'icon'},
27
+ {'id': 31, 'sort': 6, 'pid': 0, 'isLeaf': True, 'name': '无', 'code': 'none'},
28
+ {'id': 32, 'sort': 30, 'pid': 7, 'isLeaf': True, 'name': '文本框', 'code': 'textarea'},
29
+ {'id': 33, 'sort': 18, 'pid': 36, 'isLeaf': True, 'name': '时间区间', 'code': 'timerange'},
30
+ {'id': 35, 'sort': 33, 'pid': 5, 'isLeaf': True, 'name': '时间选择', 'code': 'time'},
31
+ {'id': 36, 'sort': 20, 'pid': 0, 'isLeaf': False, 'name': 'RANGE', 'code': '区间工具集'},
32
+ {'id': 37, 'sort': 38, 'pid': 36, 'isLeaf': True, 'name': '日期区间', 'code': 'daterange'},
33
+ {'id': 39, 'sort': 3, 'pid': 36, 'isLeaf': True, 'name': '多日期', 'code': 'dates'},
34
+ {'id': 54, 'sort': 54, 'pid': 7, 'isLeaf': True, 'name': '集合', 'code': 'set'}
35
+ ]
36
+
37
+ meta_field_domain = [
38
+ {
39
+ 'name': 'CharField',
40
+ 'default_id': 'text', 'align': 'left',
41
+ 'tools': [
42
+ 'text', 'number', 'meta', 'color', 'auto', 'date', 'select', 'tree', 'cascade', 'icon',
43
+ 'textarea', 'timerange', 'daterange', 'dates', 'set'
44
+ ]
45
+ },
46
+ {
47
+ 'name': 'TextField',
48
+ 'default_id': 'textarea', 'align': 'left',
49
+ 'tools': ['text', 'textarea']
50
+ },
51
+ {
52
+ 'name': 'BooleanField',
53
+ 'default_id': 'switch', 'align': 'center',
54
+ 'tools': ['switch', 'boolean']
55
+ },
56
+ {
57
+ 'name': 'IntegerField',
58
+ 'default_id': 'number', 'align': 'right',
59
+ 'tools': ['number']
60
+ },
61
+ {
62
+ 'name': 'FloatField',
63
+ 'default_id': 'number', 'align': 'right',
64
+ 'tools': ['number']
65
+ },
66
+ {
67
+ 'name': 'ForeignKey',
68
+ 'default_id': 'select', 'align': 'left',
69
+ 'tools': ['select', 'tree', 'cascade']
70
+ },
71
+ {
72
+ 'name': 'ManyToOneRel',
73
+ 'default_id': 'select', 'align': 'center',
74
+ 'tools': ['transfer', 'select', 'tree', 'cascade']
75
+ },
76
+ {
77
+ 'name': 'ManyToManyField',
78
+ 'default_id': 'select', 'align': 'center',
79
+ 'tools': [ 'transfer', 'select', 'tree', 'cascade']
80
+ },
81
+ {
82
+ 'name': 'ManyToManyRel',
83
+ 'default_id': 'select', 'align': 'center',
84
+ 'tools': ['transfer', 'select', 'tree', 'cascade']
85
+ },
86
+ {
87
+ 'name': 'OneToOneRel',
88
+ 'default_id': 'none', 'align': 'left',
89
+ 'tools': []
90
+ },
91
+ {
92
+ 'name': 'OneToOneField',
93
+ 'default_id': 'none', 'align': 'left',
94
+ 'tools': []
95
+ },
96
+ {
97
+ 'name': 'DateField',
98
+ 'default_id': 'date', 'align': 'center',
99
+ 'tools': ['date']
100
+ },
101
+ {
102
+ 'name': 'TimeField',
103
+ 'default_id': 'time', 'align': 'center',
104
+ 'tools': ['time']
105
+ },
106
+ {
107
+ 'name': 'DateTimeField',
108
+ 'default_id': 'date', 'align': 'center',
109
+ 'tools': ['date']
110
+ },
111
+ {
112
+ 'name': 'JSONField',
113
+ 'default_id': 'object', 'align': 'center',
114
+ 'tools': ['object']
115
+ },
116
+ {
117
+ 'name': 'FileField',
118
+ 'default_id': 'file', 'align': 'center',
119
+ 'tools': ['image', 'file', 'rich']
120
+ },
121
+ {
122
+ 'name': 'BigAutoField',
123
+ 'default_id': 'none', 'align': 'right',
124
+ 'tools': []
125
+ },
126
+ {
127
+ 'name': 'UUIDField',
128
+ 'default_id': 'none', 'align': 'left',
129
+ 'tools': []
130
+ },
131
+ {
132
+ 'name': 'Custom',
133
+ 'default_id': 'none', 'align': 'left',
134
+ 'tools': []
135
+ },
136
+ ]
@@ -0,0 +1,7 @@
1
+ meta_view_default_values = {
2
+ 'data.MetaView': {
3
+ '__init__': {
4
+ 'allow_insert': False
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,144 @@
1
+ from deepmerge import always_merger
2
+ from django.db.models import ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField,OneToOneField,OneToOneRel
3
+ from django.db.models import IntegerField, BooleanField, FloatField,TextField, CharField
4
+ from django.db.models import FileField, JSONField
5
+ from django.db.models import DateTimeField, TimeField, DateField
6
+
7
+
8
+
9
+ class OrmField:
10
+
11
+ def __init__(self, entity, field, is_tree):
12
+ self.entity = entity
13
+ self.model_field = field
14
+ self.is_tree = is_tree
15
+ self.not_null = not field.null
16
+ self.clazz = type(field)
17
+ self.multiple = self.clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel]
18
+
19
+ self.prop = self.__prop__()
20
+ self.domain = self.__domain__()
21
+ self.model = self.__model__()
22
+ self.label = self.__label__()
23
+ self.column_width = self.__column_width__()
24
+ self.refer = self.__refer__()
25
+ self.align = self.___align__()
26
+ self.format = self.__formating__()
27
+
28
+
29
+
30
+
31
+
32
+ def json(self):
33
+ _field = {
34
+ "prop": self.prop,
35
+ "label": self.label,
36
+ "name": self.label,
37
+ "domain": self.domain,
38
+ "refer": self.refer,
39
+ "format": self.format,
40
+ "not_null": self.not_null,
41
+ "align": self.align,
42
+ "column_width": self.column_width,
43
+ }
44
+ if self.is_tree:
45
+ if self.prop in ['pid', 'isLeaf']:
46
+ _field['hide_on_table'] = True
47
+ _field['hide_on_form'] = True
48
+ _field['hide_on_form_branch'] = True
49
+ _field['hide_on_form_leaf'] = True
50
+ elif self.prop in ['icon']:
51
+ _field['tool'] = 'icon'
52
+ return _field
53
+
54
+
55
+ def __column_width__(self):
56
+ if self.clazz in [BooleanField, FileField, JSONField]:
57
+ return 100
58
+ elif self.clazz in [DateField, DateTimeField, TimeField]:
59
+ return 120
60
+ return 0
61
+
62
+ def __label__(self):
63
+ return self.model._meta.verbose_name \
64
+ if self.clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel, OneToOneRel, OneToOneField] \
65
+ else self.model_field.verbose_name
66
+
67
+
68
+ def __model__(self):
69
+ return self.model_field.related_model \
70
+ if self.clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel, OneToOneRel, OneToOneField, ForeignKey] \
71
+ else None
72
+
73
+
74
+ def __domain__(self):
75
+ return self.clazz.__name__ \
76
+ if self.clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel ,OneToOneRel, OneToOneField] \
77
+ else self.model_field.get_internal_type()
78
+
79
+ def __prop__(self):
80
+ return self.model_field.name + "_id" \
81
+ if self.clazz in [ForeignKey,OneToOneRel, OneToOneField] \
82
+ else self.model_field.name
83
+
84
+
85
+ def ___align__(self):
86
+ if self.clazz in [FloatField, IntegerField]:
87
+ return 'right'
88
+ elif self.clazz in [BooleanField, FileField, JSONField, DateField, DateTimeField, TimeField]:
89
+ return 'center'
90
+ return 'left'
91
+
92
+ def __refer__(self):
93
+ refer = {
94
+ "entity": None,
95
+ "value": "name", "label": 'name', "display": "id",
96
+ "multiple": self.multiple, "strict": False, "remote": False,
97
+ "includes": {}, "excludes": {},
98
+ "root": 0, "isTree": self.is_tree
99
+ }
100
+ if self.model:
101
+ module, name = self.model.__module__, self.model.__name__
102
+ refer['entity'] = '%s.%s' % (module.replace('.models', '').split('.')[-1], name)
103
+ return refer
104
+
105
+ def __formating__(self):
106
+ _format = {
107
+ # 文本
108
+ "maxlength": 0,
109
+ "type": 'text',
110
+
111
+ # 数值
112
+ "min": None,
113
+ "max": None,
114
+ "step": 1,
115
+ "precision": None,
116
+ "step_strictly": False,
117
+
118
+ # 日期
119
+ "frequency": "date",
120
+
121
+ # 文件
122
+ "maximum": 5,
123
+ "accept": [],
124
+ "width": 800,
125
+ "height": 0,
126
+ "file_name_field":None,
127
+ "locked": False,
128
+
129
+ #集合
130
+ "set": {}
131
+ }
132
+ if self.clazz == CharField:
133
+ _format['maxlength'] = self.model_field.max_length
134
+ if self.clazz == TextField:
135
+ _format['type'] = "textarea"
136
+ elif self.clazz == DateTimeField:
137
+ _format['frequency'] = "datetime"
138
+ elif self.clazz == IntegerField:
139
+ _format['precision'] = 0
140
+ _format['step_strictly'] = True
141
+ return _format
142
+
143
+
144
+
@@ -0,0 +1,30 @@
1
+ import copy
2
+
3
+ from .defaults.frame_defaults import meta_field_tool, meta_field_domain
4
+
5
+ from ...data.models import MetaFieldDomain, MetaFieldTool
6
+
7
+
8
+ def init_meta_frame():
9
+ from ..dao.dao_orm import OrmDao
10
+ tool_dao = OrmDao('data.MetaFieldTool')
11
+ domain_dao = OrmDao('data.MetaFieldDomain')
12
+ mapping = {}
13
+ for item in meta_field_tool:
14
+ _id, code = item['id'], item['code']
15
+ item.update({"saved": True})
16
+ if item['isLeaf']:
17
+ mapping[code] = _id
18
+ tool_dao.save_one(item)
19
+
20
+ for row in meta_field_domain:
21
+ default_id, tools = row['default_id'], row['tools']
22
+ print(mapping[default_id])
23
+ _row = copy.deepcopy(row)
24
+ _row.update({
25
+ 'default_id': mapping[default_id],
26
+ 'tools': [mapping[tool] for tool in tools],
27
+ "saved": True
28
+ })
29
+ domain_dao.save_one(_row)
30
+ return MetaFieldDomain.objects.all()
@@ -0,0 +1,69 @@
1
+ from deepmerge import always_merger
2
+
3
+ from .defaults.view_defaults import meta_view_default_values
4
+ from ...core.dao.dao_orm import OrmDao
5
+ from ...data.models import MetaView, Meta
6
+
7
+
8
+ class OrmMeta:
9
+
10
+ def __init__(self, entity, code):
11
+ self.entity = entity
12
+ self.dao = OrmDao(entity)
13
+ self.code = code or 'default'
14
+
15
+
16
+ # load_meta
17
+ meta_dao = OrmDao('data.Meta')
18
+ _meta = {"entity": entity}
19
+ meta: Meta = meta_dao.search(_meta).first()
20
+ if meta is None:
21
+ _meta.update({"name": self.dao.model.name, 'saved': True})
22
+ meta = meta_dao.save_one(_meta)
23
+ self.meta = meta
24
+
25
+
26
+ # load_view
27
+ view_dao = OrmDao('data.MetaView')
28
+ _view = {"code": self.code, "meta_id": meta.id}
29
+ view: MetaView = view_dao.search(_view).first()
30
+ if view is None:
31
+ _view.update({"name": self.code.upper(), "saved": True})
32
+ view = view_dao.save_one(_view)
33
+ self.__init_view__(view)
34
+ self.view = view
35
+
36
+ # load_fields
37
+ if view.metafield_set.count() == 0:
38
+ field_dao = OrmDao('data.MetaField')
39
+ _fields = self.dao.model.initial_fields(code)
40
+ for _field in _fields:
41
+ _field.update({'view_id':view.id, "saved": True })
42
+ field_dao.save_one(_field)
43
+
44
+
45
+ def get_view(self):
46
+ _view = self.view.json()
47
+ meta = self.meta.json()
48
+ name, entity = meta['name'], meta['entity']
49
+ fields = self.view.metafield_set.all().order_by('-sort')
50
+ _fields = {field.prop: field.json(entity=entity, code=self.code, db='orm') for field in fields}
51
+ _view.update({
52
+ '$db': 'orm',
53
+ '$entity': entity,
54
+ '$code': self.code,
55
+ '$meta_name': name,
56
+ '$is_tree': self.dao.model.is_tree,
57
+ '$fields': _fields
58
+ })
59
+ return _view
60
+
61
+ def __init_view__(self, view: MetaView):
62
+ default_view = meta_view_default_values.get(self.entity, {})
63
+ default_values = default_view.get('__init__',{})
64
+ code_values = default_view.get(self.code, {})
65
+ values = always_merger.merge(default_values, code_values)
66
+ if len(values) > 0:
67
+ for key, value in values.items():
68
+ setattr(view, key, value)
69
+ view.save()
@@ -0,0 +1,20 @@
1
+ from django.http import HttpRequest
2
+ from django.utils.deprecation import MiddlewareMixin
3
+ from response import ValarResponse
4
+
5
+
6
+ class Middleware(MiddlewareMixin):
7
+ @staticmethod
8
+ def process_response(request: HttpRequest, response: ValarResponse):
9
+ headers = response.headers
10
+ if type(response)==ValarResponse:
11
+ message, code = response.message, response.code
12
+ headers['valar_message'] = message
13
+ headers['valar_code'] = code
14
+
15
+ keys = ['client','auth','uid']
16
+ for key in keys:
17
+ value = request.headers.get(key)
18
+ if value:
19
+ headers[key] = value
20
+ return response
valar/core/response.py ADDED
@@ -0,0 +1,7 @@
1
+ from django.http import JsonResponse
2
+
3
+ class ValarResponse(JsonResponse):
4
+ def __init__(self, data, message='', code='info'):
5
+ self.message = message
6
+ self.code = code
7
+ super(ValarResponse, self).__init__(data, safe=False)
@@ -0,0 +1,6 @@
1
+ class SingletonMeta(type):
2
+ _instances = {}
3
+ def __call__(cls, *args, **kwargs):
4
+ if cls not in cls._instances:
5
+ cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
6
+ return cls._instances[cls]
@@ -0,0 +1,82 @@
1
+ from django.apps import AppConfig
2
+ from django.db import models
3
+ from django.db.models import ManyToOneRel, OneToOneRel, ManyToManyRel, ManyToManyField, UUIDField, FileField, \
4
+ ForeignKey, OneToOneField, DateField, TimeField, DateTimeField, BigAutoField
5
+ from django.db.models.options import Options
6
+
7
+
8
+ class VModel(models.Model):
9
+ objects = models.Manager()
10
+ sort = models.BigIntegerField(null=True, verbose_name='序号')
11
+ name = models.CharField(max_length=50, null=True)
12
+ create_time = models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')
13
+ modify_time = models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')
14
+ saved = models.BooleanField(default=False)
15
+
16
+ class Meta:
17
+ abstract = True
18
+
19
+ def __str__(self):
20
+ return str(self.full())
21
+
22
+ def get_meta(self)->Options:
23
+ return getattr(self, '_meta')
24
+
25
+ def get_entity(self):
26
+ name = type(self).__name__
27
+ config: AppConfig = self.get_meta().app_config
28
+ return f'{config.label}.{name}'
29
+
30
+ def json(self, *args, **kwargs):
31
+ excludes = [ManyToOneRel, OneToOneRel, ManyToManyField, ManyToManyRel, UUIDField]
32
+ fields = [field for field in self.get_meta().get_fields() if type(field) not in excludes]
33
+ data = {}
34
+ for field in fields:
35
+ value = field.value_from_object(self)
36
+ prop = field.name
37
+ domain = type(field)
38
+ if value is not None:
39
+ if domain in [ForeignKey, OneToOneField]:
40
+ prop = f'{prop}_id'
41
+ elif domain in [DateTimeField]:
42
+ value = value.strftime('%Y-%m-%d %H:%M:%S')
43
+ elif domain in [DateField]:
44
+ value = value.strftime('%Y-%m-%d')
45
+ elif domain in [TimeField]:
46
+ value = value.strftime('%H:%M:%S')
47
+ elif domain in [FileField]:
48
+ value = value.name
49
+ elif domain in [BigAutoField]:
50
+ value = str(value)
51
+ data[prop] = value
52
+ data.update({f'${k}': v for k,v in kwargs.items()})
53
+ return data
54
+
55
+ def full(self):
56
+ includes = [ManyToManyField, ManyToManyRel, ForeignKey, ManyToOneRel, OneToOneField, OneToOneRel]
57
+ fields = [field for field in self.get_meta().get_fields() if type(field) in includes]
58
+ data = self.json()
59
+ for field in fields:
60
+ prop = field.name
61
+ domain = type(field)
62
+ if domain in [ForeignKey,OneToOneField]:
63
+ bean: VModel = getattr(self, prop)
64
+ data[prop] = bean.json() if bean else None
65
+ elif domain == OneToOneRel:
66
+ print('OneToOneRel')
67
+ pass
68
+ elif domain in [ManyToManyField,ManyToManyRel,ManyToOneRel]:
69
+ accessor = prop if domain == ManyToManyField else field.get_accessor_name()
70
+ _set = getattr(self, accessor).all().order_by('-sort')
71
+ data[prop] = [item.id for item in _set]
72
+ data[f'{prop}_set'] = [item.json() for item in _set]
73
+ return data
74
+
75
+
76
+ class VTree(VModel):
77
+ pid = models.IntegerField(null=False, default=0, verbose_name='父节点')
78
+ isLeaf = models.BooleanField( default=False, verbose_name='叶子节点')
79
+ icon = models.CharField(max_length=255, null=True, verbose_name='图标')
80
+ class Meta:
81
+ abstract = True
82
+
valar/data/apps.py ADDED
@@ -0,0 +1,22 @@
1
+ import importlib
2
+ import os
3
+
4
+ from django.apps import AppConfig
5
+ from django.conf import settings
6
+ from django.urls import include, path
7
+
8
+
9
+ class DataConfig(AppConfig):
10
+ default_auto_field = 'django.db.models.BigAutoField'
11
+ name = 'src.valar.data'
12
+
13
+ def ready(self):
14
+ run_once = os.environ.get('CMDLINERUNNER_RUN_ONCE')
15
+ if run_once is None:
16
+ os.environ['CMDLINERUNNER_RUN_ONCE'] = 'True'
17
+ root = settings.ROOT_URLCONF
18
+ module = importlib.import_module(root)
19
+ urlpatterns = getattr(module,'urlpatterns')
20
+
21
+
22
+