valar 1.0.29__py3-none-any.whl → 1.1.1__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 (61) hide show
  1. {valar/channels → channels}/consumer.py +1 -1
  2. {valar/channels → channels}/mapping.py +5 -3
  3. {valar/channels → channels}/sender.py +5 -1
  4. {valar/channels → channels}/views.py +1 -1
  5. classes/auto_migration_mixin.py +7 -0
  6. classes/auto_urlpatterns_mixin.py +15 -0
  7. {valar/data/migrations → migrations}/0001_initial.py +12 -11
  8. models/__init__.py +1 -0
  9. models/frame.py +30 -0
  10. valar/data/models.py → models/meta.py +4 -32
  11. {valar-1.0.29.dist-info → valar-1.1.1.dist-info}/METADATA +1 -1
  12. valar-1.1.1.dist-info/RECORD +25 -0
  13. valar-1.1.1.dist-info/top_level.txt +6 -0
  14. valar/channels/__init__.py +0 -1
  15. valar/core/dao/_mon_array2tree.py +0 -18
  16. valar/core/dao/dao_base.py +0 -50
  17. valar/core/dao/dao_mon.py +0 -76
  18. valar/core/dao/dao_orm.py +0 -99
  19. valar/core/dao/engine.py +0 -12
  20. valar/core/dao/engine_minio.py +0 -91
  21. valar/core/dao/engine_mon.py +0 -34
  22. valar/core/dao/engine_orm.py +0 -25
  23. valar/core/dao/model_mon.py +0 -24
  24. valar/core/dao/model_orm.py +0 -198
  25. valar/core/dao/query_mon.py +0 -12
  26. valar/core/dao/query_orm.py +0 -44
  27. valar/core/dao/utils_orm.py +0 -87
  28. valar/core/dao_abstract.py +0 -63
  29. valar/core/meta/defaults/field_keys_default.py +0 -17
  30. valar/core/meta/defaults/field_values_default.py +0 -85
  31. valar/core/meta/defaults/frame_defaults.py +0 -136
  32. valar/core/meta/defaults/view_defaults.py +0 -20
  33. valar/core/meta/field_orm.py +0 -146
  34. valar/core/meta/init_meta_frame.py +0 -32
  35. valar/core/meta/meta_orm.py +0 -74
  36. valar/core/middleware.py +0 -20
  37. valar/data/__init__.py +0 -0
  38. valar/data/apps.py +0 -13
  39. valar/data/migrations/0002_remove_metaview_allow_batch.py +0 -17
  40. valar/data/migrations/0003_remove_metaview_allow_pop_metaview_allow_order_and_more.py +0 -27
  41. valar/data/migrations/0004_rename_allow_sort_metafield_allow_order.py +0 -18
  42. valar/data/migrations/__init__.py +0 -0
  43. valar/data/urls.py +0 -23
  44. valar/data/views/__init__.py +0 -0
  45. valar/data/views/file.py +0 -12
  46. valar/data/views/handler.py +0 -41
  47. valar/data/views/rest.py +0 -89
  48. valar-1.0.29.dist-info/RECORD +0 -55
  49. valar-1.0.29.dist-info/top_level.txt +0 -1
  50. {valar → channels}/__init__.py +0 -0
  51. {valar/channels → channels}/executer.py +0 -0
  52. {valar/core → classes}/__init__.py +0 -0
  53. {valar/core → classes}/counter.py +0 -0
  54. {valar/core → classes}/singleton_meta.py +0 -0
  55. /valar/core/response.py → /classes/valar_response.py +0 -0
  56. {valar/core/dao → frame}/__init__.py +0 -0
  57. {valar/core/meta → migrations}/__init__.py +0 -0
  58. /valar/core/valar_models.py → /models/core.py +0 -0
  59. {valar-1.0.29.dist-info → valar-1.1.1.dist-info}/WHEEL +0 -0
  60. {valar-1.0.29.dist-info → valar-1.1.1.dist-info}/licenses/LICENSE +0 -0
  61. {valar/core/meta/defaults → views}/__init__.py +0 -0
@@ -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)
@@ -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)
@@ -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
@@ -1,198 +0,0 @@
1
- import copy
2
-
3
- from bson import ObjectId
4
- from bson.errors import InvalidId
5
- from deepmerge import always_merger
6
- from django.db.models import ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, OneToOneRel
7
- from django.db.models import QuerySet
8
- from django.db.models import Manager
9
- from django.db.models.fields.files import FieldFile
10
- from django.forms import FileField
11
-
12
- from .engine_minio import MinioEngine
13
- from .utils_orm import OrmUtils
14
- from ..meta.defaults.field_keys_default import meta_field_key_defaults
15
- from ..meta.defaults.field_values_default import meta_field_value_defaults
16
- from ..meta.field_orm import OrmField
17
- from ..valar_models import VModel, VTree
18
- from ...data.models import MetaFieldDomain
19
-
20
-
21
- class OrmModel:
22
-
23
- def __init__(self, mod, entity):
24
- self.entity = entity
25
- self.model = mod
26
- meta = getattr(mod, '_meta')
27
- self.name = meta.verbose_name
28
- self.is_tree = issubclass(mod, VTree)
29
- self.manager: Manager = mod.objects
30
- fields = meta.get_fields()
31
- mapping = {}
32
- for f in fields:
33
- field = OrmField(entity, f, self.is_tree)
34
- mapping[field.prop] = field
35
- self.mapping = mapping
36
- self.minio = MinioEngine()
37
- self.bucket_name = self.minio.get_bucket_name(entity)
38
-
39
- @staticmethod
40
- def object_id(_id):
41
- try:
42
- return int(_id)
43
- except TypeError:
44
- return None
45
-
46
-
47
- def props(self, domain=None):
48
- array = []
49
- for prop in self.mapping:
50
- field: OrmField = self.mapping[prop]
51
- if field.domain == domain or domain is None:
52
- array.append(prop)
53
- return array
54
-
55
-
56
-
57
- def initial_fields(self, code):
58
- props = self.props()
59
- default_keys = meta_field_key_defaults.get(self.entity,{})
60
- method, array = default_keys.get(code, ('omit',[]))
61
- def fun(prop): return prop not in array if method == 'omit' else prop in array
62
- props = [prop for prop in props if fun(prop)]
63
-
64
- default_values = meta_field_value_defaults.get(self.entity, {})
65
- init_values = default_values.get('__init__', {})
66
- code_values = default_values.get(code, {})
67
- default_fields = always_merger.merge(init_values, code_values)
68
-
69
- values = MetaFieldDomain.objects.all().values('name', 'default__code', 'align')
70
- meta_frame = {
71
- vs['name']: {
72
- "tool": vs['default__code'],
73
- "align": vs['align'],
74
- }
75
- for vs in values
76
- }
77
- fields = []
78
- for prop in props:
79
- field = self.get_field(prop)
80
- field_json = field.json()
81
- frame = copy.deepcopy(meta_frame.get(field.domain, {}))
82
- refer = field_json['refer']
83
- if refer['isTree'] and frame.get('tool') == 'select' :
84
- frame['tool'] = 'tree'
85
- elif self.is_tree and prop =='icon':
86
- frame['tool'] = 'icon'
87
- field_json.update(frame)
88
- default_field = default_fields.get(prop, {})
89
- always_merger.merge(field_json, default_field)
90
- fields.append(field_json)
91
- fields.reverse()
92
- return fields
93
-
94
- def get_field(self, prop)->OrmField:
95
- return self.mapping[prop]
96
-
97
- def detach_item(self, item):
98
- _id = item.get('id')
99
- if _id:
100
- del item['id']
101
- simple_item = {}
102
- complex_item = {}
103
- for prop in item:
104
- field = self.get_field(prop)
105
- value = item.get(prop)
106
- if field.domain in ['ManyToOneRel', 'ManyToManyField', 'ManyToManyRel', 'OneToOneRel', 'OneToOneField','FileField']:
107
- complex_item[prop] = value
108
- else:
109
- simple_item[prop] = value
110
- return self.object_id(_id), simple_item, complex_item
111
-
112
- def get_file_paths(self, query_set: QuerySet):
113
- props = self.props('FileField')
114
- items = query_set.values(*props)
115
- array = []
116
- for item in items:
117
- array += [i for i in item.values() if i]
118
- return array
119
-
120
- def remove_files(self, query_set: QuerySet):
121
- paths = self.get_file_paths(query_set)
122
- for path in paths:
123
- self.minio.remove_path(path)
124
-
125
- def save_complex_field(self, complex_item, bean):
126
- for prop in complex_item:
127
- value = complex_item[prop]
128
- field = self.get_field(prop).model_field
129
- clazz = type(field)
130
- if clazz == ManyToManyField:
131
- m2m = getattr(bean, prop)
132
- m2m.clear()
133
- m2m.add(*value)
134
- elif clazz == ManyToOneRel:
135
- getattr(bean, field.get_accessor_name()).clear()
136
- remote_model: VModel = field.related_model
137
- new_set: QuerySet = remote_model.objects.filter(id__in=value)
138
- remote_field: ForeignKey = field.remote_field
139
- k = remote_field.get_attname()
140
- new_set.update(**{k: bean.id})
141
- elif clazz == ManyToManyRel:
142
- getattr(bean, field.get_accessor_name()).clear()
143
- remote_model: VModel = field.related_model
144
- remote_items: QuerySet = remote_model.objects.filter(id__in=value)
145
- remote_field: ManyToManyField = field.remote_field
146
- remote_field_prop = remote_field.get_attname()
147
- for _bean in remote_items:
148
- bean_set = getattr(_bean, remote_field_prop)
149
- bean_set.add(bean)
150
- elif clazz == OneToOneRel:
151
- remote_model: VModel = field.related_model
152
- remote_field: OneToOneField = field.remote_field
153
- remote_field_prop = remote_field.get_attname()
154
- _bean = remote_model.objects.get(id=value)
155
- __bean = remote_model.objects.filter(**{remote_field_prop: bean.id}).first()
156
- if __bean:
157
- setattr(__bean, remote_field_prop, None)
158
- __bean.save()
159
- setattr(_bean, remote_field_prop, bean.id)
160
- _bean.save()
161
- elif clazz == OneToOneField:
162
- __bean = field.model.objects.filter(**{prop: value}).first()
163
- if __bean:
164
- setattr(__bean, prop, None)
165
- __bean.save()
166
- setattr(bean, prop, value)
167
- elif clazz == FileField:
168
- file_name, _bytes = value
169
- field_file: FieldFile = getattr(bean, prop)
170
- if field_file:
171
- path = field_file.name
172
- self.minio.remove_path(path)
173
- object_name = self.minio.get_object_name(bean.id, prop, file_name)
174
- path = self.minio.upload(self.bucket_name, object_name, _bytes) if _bytes else None
175
- setattr(bean, prop, path)
176
-
177
-
178
-
179
-
180
- def to_dict(self, query_set: QuerySet, code=None):
181
- # query_set = query_set.filter(saved=True)
182
- utils = OrmUtils()
183
- orm_fields = self.mapping.values()
184
- # 简单字段取值
185
- simple_props = [field.prop for field in orm_fields if field.domain not in utils.referred_domains]
186
- custom_props = utils.custom_props(self.entity, code)
187
- results = list(query_set.filter().values(*[*simple_props, *custom_props]))
188
- utils.date_values(orm_fields, results)
189
- # 关系型字段取值
190
- mapping = { row['id']: row for row in results}
191
- referred_fields = [field for field in orm_fields if field.domain in utils.referred_domains]
192
- pks = mapping.keys()
193
- for field in referred_fields:
194
- manager: Manager = query_set.model.objects
195
- qs = manager.filter(id__in=pks)
196
- utils.linkage(field, qs, mapping)
197
- return results
198
-
@@ -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
-
@@ -1,44 +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
- conditions = conditions or []
25
- self.orders = __translate_orders__(orders or {'sort': -1})
26
- conditions = conditions if len(conditions) else [{'includes':{},'excludes':{}}]
27
- self.includes = __translate_condition__(conditions,'includes')
28
- self.excludes = __translate_condition__(conditions, 'excludes')
29
-
30
- @staticmethod
31
- def is_empty(conditions):
32
- if conditions and len(conditions):
33
- temp = {}
34
- for cond in conditions:
35
- temp.update(cond)
36
- return len(temp.keys()) == 0
37
- else:
38
- return True
39
-
40
-
41
-
42
-
43
-
44
-
@@ -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)
@@ -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
-
@@ -1,17 +0,0 @@
1
- __mf_common__ = ['prop','name']
2
-
3
- meta_field_key_defaults = {
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
- }
@@ -1,85 +0,0 @@
1
-
2
- meta_field_value_defaults = {
3
- 'data.MetaFieldDomain':{
4
- "__init__":{
5
- "default_id":{
6
- "tool":"tree"
7
- },
8
- "search_id":{
9
- "tool":"tree"
10
- },
11
- "tools":{
12
- "tool":"tree",
13
- "refer": {
14
- "display":"code"
15
- }
16
- },
17
- "align":{
18
- "tool":"set",
19
- "format":{
20
- "set": {
21
- 'left':'左对齐',
22
- 'right':'右对齐',
23
- 'center':'剧中对齐',
24
- }
25
- }
26
- }
27
- }
28
- },
29
- 'data.MetaField':{
30
- "__init__":{
31
- "column_width":{
32
- 'unit':'px'
33
- },
34
- "fixed":{
35
- "tool":"set",
36
- "format":{
37
- "set": {
38
- 'left':'左侧固定',
39
- 'right':'右侧固定',
40
- }
41
- }
42
- },
43
- "align":{
44
- "tool":"set",
45
- "format":{
46
- "set": {
47
- 'left':'左对齐',
48
- 'right':'右对齐',
49
- 'center':'剧中对齐',
50
- }
51
- }
52
- },
53
- "prop":{
54
- 'allow_edit': False,
55
- 'column_width': 120
56
- },
57
- "domain":{
58
- 'allow_edit': False,
59
- 'column_width': 120,
60
- },
61
- "tool":{
62
- 'column_width': 100,
63
- 'tool': 'tree',
64
- 'refer': {
65
- 'entity':'data.MetaFieldTool',
66
- 'includes': {'metafielddomain__name':'${domain}'},
67
- 'value': 'code','display':'code'
68
- }
69
-
70
- },
71
- "span":{
72
- 'column_width': 100,
73
- "format": { "min": 0, "max": 24, "step": 1, "precision": 0, "step_strictly": True }
74
- },
75
- "refer":{
76
- 'allow_edit': False,
77
- 'column_width': 80
78
- },
79
- "format":{
80
- 'allow_edit': False,
81
- 'column_width': 80
82
- },
83
- }
84
- }
85
- }