valar 1.0.20__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 +1 -98
  40. valar/data/models.py +2 -122
  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.20.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.20.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 -49
  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.20.dist-info/RECORD +0 -27
  63. {valar-1.0.20.dist-info → valar-1.0.22.dist-info}/licenses/LICENSE +0 -0
  64. {valar-1.0.20.dist-info → valar-1.0.22.dist-info}/top_level.txt +0 -0
@@ -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
@@ -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
-
@@ -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
- }
@@ -1,49 +0,0 @@
1
- import os
2
-
3
- from django.db import OperationalError
4
-
5
- from ...data.models import MetaFieldDomain, MetaFieldTool
6
- import pandas as pd
7
-
8
-
9
- def load_meta_frame():
10
- try:
11
- MetaFieldTool.objects.all().delete()
12
- MetaFieldDomain.objects.all().delete()
13
- project_root = os.path.dirname(os.path.abspath(__file__))
14
- file_path = os.path.join(project_root, 'meta_frame.xlsx')
15
- array = pd.read_excel(file_path, sheet_name='tool').to_dict("records")
16
- for row in array:
17
- row['saved'] = True
18
- MetaFieldTool.objects.create(**row)
19
- array = pd.read_excel(file_path, sheet_name='domain').to_dict("records")
20
- for row in array:
21
- row['saved'] = True
22
- tools = row.get('tools', '').split(';')
23
- del row['tools']
24
- item = MetaFieldDomain.objects.create(**row)
25
- for tk in tools:
26
- item.tools.add(tk)
27
- except OperationalError as e:
28
- print('initialization')
29
-
30
-
31
- def convert_meta_fields(fields, entity):
32
- values = MetaFieldDomain.objects.all().values('name', 'default__code', 'align')
33
- mapping = {vs['name']: {
34
- "tool": vs['default__code'],
35
- "align": vs['align']
36
- } for vs in values}
37
- array = []
38
- for field in fields:
39
- node = mapping[field.domain]
40
- _field = field.json
41
- if field.tool == 'default':
42
- _field['tool'] = node['tool']
43
- _field['align'] = node['align']
44
- _field['entity'] = entity
45
- array.append(_field)
46
- return array
47
-
48
-
49
-
@@ -1,200 +0,0 @@
1
- from django.db.models import (ManyToOneRel, ForeignKey, ManyToManyRel, ManyToManyField, OneToOneField, CharField,
2
- OneToOneRel, IntegerField, BooleanField, FloatField, FileField, JSONField, DateField,
3
- TextField,DateTimeField, TimeField)
4
-
5
- from .meta_frame import convert_meta_fields
6
- from ..orm.meta import meta_props, meta_defaults
7
- from ..models import Meta, MetaView, VModel, MetaField, VTree
8
-
9
- from deepmerge import always_merger
10
-
11
-
12
- def __save_model(model):
13
- model.save()
14
- model.sort = model.id
15
- model.saved = True
16
- model.save()
17
-
18
-
19
-
20
- def load_view(entity, code, name, fields):
21
- meta = Meta.objects.filter(entity=entity).first()
22
- if meta is None:
23
- meta = Meta(entity=entity, name=name)
24
- __save_model(meta)
25
- view = MetaView.objects.filter(meta__entity=entity, code=code).first()
26
- if view is None:
27
- view = MetaView(meta=meta, code=code, view_name=code.upper())
28
- __save_model(view)
29
- if view.metafield_set.count() == 0:
30
- t, p = meta_props.get(entity, {}).get(code,('omit',[]))
31
- _fields = [f for f in fields if f['prop'] not in p] if t=='omit' else [f for f in fields if f['prop'] in p]
32
- defaults = meta_defaults.get(entity,{})
33
- for _field in _fields:
34
- prop = _field['prop']
35
- _field = always_merger.merge(_field,defaults.get(prop,{}))
36
- _fields.reverse()
37
- for f in _fields:
38
- f['view'] = view
39
- field = MetaField.objects.create(**f)
40
- __save_model(field)
41
- return view
42
-
43
- def load_meta(view):
44
- _view = view.full
45
- _meta = _view['meta']
46
- fields = view.metafield_set.all().order_by('-sort')
47
- _fields = convert_meta_fields(fields,_meta['entity'])
48
- # _fields = [f.json for f in fields]
49
- clear_item(_view, 'meta_id', 'metafield', 'metafield_set', 'meta')
50
- _view['meta_name'] = _meta['name']
51
- _view['entity'] = _meta['entity']
52
- _view['fields'] = {}
53
- for _field in _fields:
54
- clear_item(_field, 'view_id')
55
- prop = _field['prop']
56
- _view['fields'][prop] = _field
57
- return _view
58
-
59
-
60
-
61
- def clear_item(item, *keys):
62
- del item['saved']
63
- del item['sort']
64
- del item['create_time']
65
- del item['modify_time']
66
- for key in keys:
67
- del item[key]
68
-
69
-
70
- def get_default_refer():
71
- return {
72
- "entity": None,
73
- "value": "name", "label": 'name', "display": "id",
74
- "strict": False, "remote": False, "multiple": False,
75
- "includes": {}, "excludes": {}, "root": 0, "isTree": False
76
- }
77
-
78
-
79
- def get_refer(model, multiple = False):
80
- module, name = model.__module__, model.__name__
81
- entity = '%s.%s' % (module.replace('.models', '').split('.')[-1], name)
82
- return {
83
- "entity": entity,
84
- "value": "id", "label": 'name', "display": "id",
85
- "strict": False, "remote": False, "multiple": multiple,
86
- "includes": {}, "excludes": {}, "root": 0, "isTree": issubclass(model, VTree)
87
- }
88
-
89
- def get_align(clazz):
90
- if clazz in [FloatField, IntegerField]: #, ManyToManyRel, ManyToManyField, ManyToOneRel
91
- return 'right'
92
- elif clazz in [BooleanField,FileField,JSONField,DateField,DateTimeField,TimeField]:
93
- return 'center'
94
- return 'left'
95
-
96
- def get_default_format():
97
- return {
98
- # 文本
99
- "maxlength": 0,
100
- "type": 'text',
101
-
102
- # 数值
103
- "min": None,
104
- "max": None,
105
- "step": 1,
106
- "precision": None,
107
- "step_strictly": False,
108
-
109
- # 日期
110
- "frequency": "date",
111
-
112
- # 文件
113
- "maximum": 5,
114
- "width": 800,
115
- "height": 0,
116
- "accept": [],
117
- "file_name_field":None,
118
- "locked": False,
119
-
120
- #集合
121
- "set": {}
122
- }
123
-
124
-
125
-
126
- def get_format(field):
127
- clazz = type(field)
128
- _format = get_default_format()
129
- if clazz == CharField:
130
- _format['maxlength'] = field.max_length
131
- if clazz == TextField:
132
- _format['type'] = "textarea"
133
- elif clazz == DateTimeField:
134
- _format['frequency'] = "datetime"
135
- elif clazz == IntegerField:
136
- _format['precision'] = 0
137
- _format['step_strictly'] = True
138
- elif clazz == FileField:
139
- pass
140
- return _format
141
-
142
- def get_field_column_width(field,clazz):
143
- if clazz in [BooleanField, FileField, JSONField]:
144
- return 100
145
- elif clazz in [ DateField, DateTimeField, TimeField]:
146
- return 120
147
- return 0
148
-
149
-
150
-
151
- def load_meta_field(field, isTree):
152
- clazz = type(field)
153
- if clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel]:
154
- prop = field.name
155
- domain = clazz.__name__
156
- model: VModel= field.related_model
157
- label = model._meta.verbose_name
158
- refer = get_refer(model, True)
159
- elif clazz in [ForeignKey]:
160
- prop = field.name + "_id"
161
- domain = field.get_internal_type()
162
- model: VModel = field.related_model
163
- label = field.verbose_name
164
- refer = get_refer(model)
165
- elif clazz in [OneToOneRel, OneToOneField]:
166
- prop = field.name + "_id"
167
- domain = clazz.__name__
168
- model: VModel = field.related_model
169
- label = model._meta.verbose_name
170
- refer = get_refer(model)
171
- else:
172
- prop = field.name
173
- domain = field.get_internal_type()
174
- label = field.verbose_name
175
- refer = get_default_refer()
176
- not_null = not field.null
177
- align = get_align(clazz)
178
- _format = get_format(field)
179
- column_width = get_field_column_width(field,clazz)
180
- _field = {
181
- "prop": prop,
182
- "label":label,
183
- "name":label,
184
- "domain":domain,
185
- "refer":refer,
186
- "format":_format,
187
- "not_null":not_null,
188
- "align":align,
189
- "column_width":column_width
190
- }
191
-
192
- if isTree:
193
- if prop in ['pid','isLeaf']:
194
- _field['hide_on_table'] = True
195
- _field['hide_on_form'] = True
196
- _field['hide_on_form_branch'] = True
197
- _field['hide_on_form_leaf'] = True
198
- elif prop in ['icon']:
199
- _field['tool'] = 'icon'
200
- return _field