valar 1.0.17__py3-none-any.whl → 1.0.18__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.

@@ -0,0 +1,36 @@
1
+ # Generated by Django 4.2.20 on 2025-05-05 06:50
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('data', '0001_initial'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.CreateModel(
14
+ name='ValaTree',
15
+ fields=[
16
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
18
+ ('name', models.CharField(max_length=50, null=True)),
19
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
20
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
21
+ ('saved', models.BooleanField(default=False)),
22
+ ('pid', models.IntegerField(default=0, verbose_name='父节点')),
23
+ ('isLeaf', models.BooleanField(default=False, verbose_name='叶子节点')),
24
+ ('icon', models.CharField(max_length=255, null=True, verbose_name='图标')),
25
+ ('text', models.TextField(null=True, verbose_name='text')),
26
+ ],
27
+ options={
28
+ 'verbose_name': '树形测试',
29
+ },
30
+ ),
31
+ migrations.AlterField(
32
+ model_name='metafield',
33
+ name='allow_sort',
34
+ field=models.BooleanField(default=True, verbose_name='可排序'),
35
+ ),
36
+ ]
valar/data/models.py CHANGED
@@ -2,6 +2,7 @@ from django.db import models
2
2
  from django.db.models.fields.files import FieldFile
3
3
 
4
4
 
5
+
5
6
  class VModel(models.Model):
6
7
  sort = models.BigIntegerField(null=True, verbose_name='序号')
7
8
  name = models.CharField(max_length=50, null=True)
@@ -69,7 +70,7 @@ class VModel(models.Model):
69
70
  elif domain in ['ManyToManyField', 'ManyToManyRel', 'ManyToOneRel']:
70
71
  accessor = prop if domain == 'ManyToManyField' else field.get_accessor_name()
71
72
  try:
72
- _set = getattr(self, accessor).all()
73
+ _set = getattr(self, accessor).all().order_by('sort')
73
74
  data[prop] = [item.id for item in _set]
74
75
  data[f'{prop}_set'] = [item.json for item in _set]
75
76
  except Exception as e:
@@ -138,22 +139,22 @@ class MetaField(VModel):
138
139
 
139
140
 
140
141
  """rest"""
141
- unit = models.CharField(max_length=55, verbose_name='单位符', null=True)
142
142
  not_null = models.BooleanField(default=False, verbose_name='不为空') #
143
- read_only = models.BooleanField(default=False, verbose_name='只读')
144
- sortable = models.BooleanField(default=False, verbose_name='可排序')
143
+ allow_edit = models.BooleanField(default=True, verbose_name='可编辑')
144
+ allow_sort = models.BooleanField(default=True, verbose_name='可排序')
145
145
  allow_search = models.BooleanField(default=True, verbose_name='可搜索')
146
146
  allow_download = models.BooleanField(default=True, verbose_name='可下载')
147
147
  allow_upload = models.BooleanField(default=False, verbose_name='可上传')
148
148
  allow_update = models.BooleanField(default=False, verbose_name='可更新')
149
149
 
150
150
  """table"""
151
+ unit = models.CharField(max_length=55, verbose_name='单位符', null=True)
151
152
  column_width = models.FloatField(default=0, verbose_name='表头宽度')
152
153
  align = models.CharField(max_length=55, default='left', verbose_name='对齐方式') #
153
154
  fixed = models.CharField(max_length=100, verbose_name='固定位置', null=True)
154
155
  header_color = models.CharField(max_length=55, verbose_name='表头颜色', null=True)
155
156
  cell_color = models.CharField(max_length=55, verbose_name='单元颜色', null=True)
156
- edit_on_table = models.BooleanField(default=False, verbose_name='表格编辑')
157
+ edit_on_table = models.BooleanField(default=True, verbose_name='表格编辑')
157
158
  hide_on_table = models.BooleanField(default=False, verbose_name='表内隐藏')
158
159
 
159
160
  """form"""
@@ -164,6 +165,7 @@ class MetaField(VModel):
164
165
  hide_on_form_branch = models.BooleanField(default=False, verbose_name='分支隐藏')
165
166
  hide_on_form_leaf = models.BooleanField(default=False, verbose_name='叶子隐藏')
166
167
 
168
+
167
169
  class Meta:
168
170
  verbose_name = '视图字段'
169
171
 
@@ -191,8 +193,10 @@ class MetaFieldDomain(VModel):
191
193
  verbose_name = '元数据字段类型'
192
194
 
193
195
 
194
-
195
-
196
+ class ValaTree(VTree):
197
+ text = models.TextField(null=True, verbose_name='text')
198
+ class Meta:
199
+ verbose_name = '树形测试'
196
200
 
197
201
  class Vala(VModel):
198
202
  text_field = models.TextField(null=True, verbose_name='text')
@@ -1,12 +1,14 @@
1
1
  from bson import ObjectId
2
- from django.db.models import QuerySet
3
- from pymongo.results import InsertOneResult, UpdateResult
2
+ from pymongo.results import InsertOneResult
4
3
 
5
4
  from django.conf import settings
6
5
  import pymongo
7
6
 
8
7
  from ..query import Query
9
8
 
9
+ from pymongo import MongoClient
10
+ from typing import Dict, Any, List, Optional
11
+
10
12
  try:
11
13
  MONGO = settings.MONGO_SETTINGS
12
14
  except AttributeError:
@@ -71,14 +73,51 @@ class MongoDao:
71
73
  def find_one(self, _id):
72
74
  return self.collection.find_one({'_id': ObjectId(_id)})
73
75
 
74
- def find_many(self, query: Query, size=0, page=1) -> [QuerySet, int]:
76
+ def find_many(self, query: Query, size=0, page=1) :
75
77
  skip = (page - 1) * size
76
78
  condition = query.mon_conditions()
77
79
  total = self.collection.count_documents(condition)
78
- cursor = self.collection.find(condition).sort(query.orders).skip(skip).limit(size)
79
- return [cursor, total]
80
+ cursor = self.collection.find(condition)
81
+
82
+ sort_fields = []
83
+ for key, value in query.orders.items():
84
+ sort_direction = pymongo.DESCENDING if value == -1 else pymongo.ASCENDING
85
+ sort_fields.append((key, sort_direction))
80
86
 
87
+ if sort_fields:
88
+ cursor = cursor.sort(sort_fields)
89
+
90
+ if size:
91
+ cursor = cursor.skip(skip).limit(size)
92
+
93
+ return cursor, total
81
94
 
82
95
  def meta(self):
83
96
  one = self.collection.find_one()
84
97
  return one
98
+
99
+ class MongoDBQuery:
100
+ #Mongo的查询
101
+ def __init__(self, connection_string: str, database_name: str):
102
+ self.client = MongoClient(connection_string)
103
+ self.db = self.client[database_name]
104
+
105
+ def find(self, collection: str, query: Dict[str, Any],
106
+ projection: Optional[Dict[str, Any]] = None,
107
+ sort: Optional[List[tuple]] = None,
108
+ limit: Optional[int] = None,
109
+ skip: Optional[int] = None) -> List[Dict[str, Any]]:
110
+ cursor = self.db[collection].find(query, projection)
111
+ if sort:
112
+ cursor = cursor.sort(sort) #好像有警告……但是能跑
113
+ if skip:
114
+ cursor = cursor.skip(skip)
115
+ if limit:
116
+ cursor = cursor.limit(limit)
117
+ return list(cursor)
118
+
119
+ def count(self, collection: str, query: Dict[str, Any]) -> int:
120
+ return self.db[collection].count_documents(query)
121
+
122
+ def close(self):
123
+ self.client.close()
@@ -0,0 +1,91 @@
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
@@ -21,6 +21,9 @@ def load_model(entity=None):
21
21
  mapping[key] = [mod, verbose_name]
22
22
  return mapping.get(entity) if entity else mapping
23
23
 
24
+
25
+
26
+
24
27
  class OrmDao:
25
28
  def __init__(self, entity):
26
29
  self.entity = entity
@@ -39,6 +42,26 @@ class OrmDao:
39
42
  self.meta_fields[prop] = _field
40
43
 
41
44
 
45
+ def tree(self, query: Query, root_id = 0):
46
+ all_set, _ = self.find_many(Query())
47
+ includes, excludes = query.orm_conditions()
48
+ print(root_id)
49
+ if not len(includes) + len(excludes) + root_id:
50
+ return all_set
51
+ values = all_set.values('id','pid')
52
+ mapping = {item['id']: item['pid'] for item in values}
53
+ results, _ = self.find_many(query)
54
+ id_set = {root_id}
55
+ for item in results:
56
+ _id = item.id
57
+ route = []
58
+ while _id is not None:
59
+ route.append(_id)
60
+ _id = mapping.get(_id)
61
+ if root_id in route:
62
+ id_set.update(route)
63
+ return all_set.filter(id__in=id_set).order_by('-sort')
64
+
42
65
  def save_one(self, item):
43
66
  _item = detach_props(item, self.meta_fields.values())
44
67
  _id = item.get('id',0)
@@ -67,7 +90,7 @@ class OrmDao:
67
90
  def find_one(self, _id):
68
91
  return self.manager.filter(id=_id).first()
69
92
 
70
- def find_many(self, query: Query, size=0, page=1)->[QuerySet, int]:
93
+ def find_many(self, query: Query, size=0, page=1):
71
94
  includes, excludes = query.orm_conditions()
72
95
  query_set = self.manager.filter(includes).exclude(excludes).order_by(*query.orm_orders())
73
96
  total = query_set.count()
@@ -78,7 +101,7 @@ class OrmDao:
78
101
 
79
102
 
80
103
  def meta(self, code:str = 'default'):
81
- omit = [ 'sort', 'create_time', 'modify_time']
104
+ omit = [ 'id', 'saved', 'sort', 'create_time', 'modify_time']
82
105
  fields = [ self.meta_fields[prop] for prop in self.meta_fields if prop not in omit]
83
106
  view = load_view(self.entity, code, self.name, fields)
84
107
  return load_meta(view)
valar/data/orm/meta.py CHANGED
@@ -1,24 +1,46 @@
1
1
  mf_common = ['prop','name','domain']
2
2
 
3
- field_props = {
3
+ meta_props = {
4
4
  'data.Meta': {
5
5
  'default': ('pick', ['entity','name']),
6
6
  },
7
7
  'data.MetaView': {
8
8
  'list': ('pick', ['meta_id','code','view_name']),
9
- 'control':('omit', ['name','meta_id', 'code', 'view_name', 'metafield'])
10
9
  },
11
10
  'data.MetaField': {
11
+ 'add': ('pick',[*mf_common]),
12
12
  'tool': ('pick',[*mf_common,'tool','refer','format']),
13
- 'rest': ('pick',[*mf_common,'not_null','read_only','unit','sortable','allow_search','allow_download','allow_upload','allow_update']),
14
- 'table': ('pick',[*mf_common,'column_width','fixed','align','edit_on_table','hide_on_table','header_color','cell_color']),
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
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
16
  }
17
17
  }
18
18
 
19
19
 
20
- field_default = {
20
+ meta_defaults = {
21
21
  'data.MetaField':{
22
-
22
+ "prop":{
23
+ 'allow_edit': False,
24
+ 'column_width': 100
25
+ },
26
+ "domain":{
27
+ 'allow_edit': False,
28
+ 'column_width': 100
29
+ },
30
+ "tool":{
31
+ 'column_width': 100
32
+ },
33
+ "span":{
34
+ 'column_width': 100,
35
+ "format": { "min": 0, "max": 24, "step": 1, "precision": 0, "step_strictly": True }
36
+ },
37
+ "refer":{
38
+ 'allow_edit': False,
39
+ 'column_width': 80
40
+ },
41
+ "format":{
42
+ 'allow_edit': False,
43
+ 'column_width': 80
44
+ },
23
45
  }
24
46
  }
@@ -2,7 +2,7 @@ from django.db.models import (ManyToOneRel, ForeignKey, ManyToManyRel, ManyToMan
2
2
  OneToOneRel, IntegerField, BooleanField, FloatField, FileField, JSONField, DateField,
3
3
  TextField,DateTimeField, TimeField)
4
4
 
5
- from ..orm.meta import field_props
5
+ from ..orm.meta import meta_props, meta_defaults
6
6
  from ..models import Meta, MetaView, VModel, MetaField
7
7
 
8
8
 
@@ -26,8 +26,14 @@ def load_view(entity, code, name, fields):
26
26
  view = MetaView(meta=meta, code=code, view_name=code.upper())
27
27
  __save_model(view)
28
28
  if view.metafield_set.count() == 0:
29
- t, p = field_props.get(entity, {}).get(code,('omit',[]))
29
+ t, p = meta_props.get(entity, {}).get(code,('omit',[]))
30
30
  _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]
31
+ defaults = meta_defaults.get(entity,{})
32
+ for _field in _fields:
33
+ prop = _field['prop']
34
+ _field.update(defaults.get(prop,{}))
35
+
36
+ _fields.reverse()
31
37
  for f in _fields:
32
38
  f['view'] = view
33
39
  field = MetaField.objects.create(**f)
@@ -37,7 +43,8 @@ def load_view(entity, code, name, fields):
37
43
  def load_meta(view):
38
44
  _view = view.full
39
45
  _meta = _view['meta']
40
- _fields = _view['metafield_set']
46
+ fields = view.metafield_set.all().order_by('-sort')
47
+ _fields = [f.json for f in fields]
41
48
  clear_item(_view, 'meta_id', 'metafield', 'metafield_set', 'meta')
42
49
  _view['meta_name'] = _meta['name']
43
50
  _view['entity'] = _meta['entity']
@@ -53,14 +60,12 @@ def load_meta(view):
53
60
  def clear_item(item, *keys):
54
61
  del item['saved']
55
62
  del item['sort']
56
- del item['id']
57
63
  del item['create_time']
58
64
  del item['modify_time']
59
65
  for key in keys:
60
66
  del item[key]
61
67
 
62
68
 
63
-
64
69
  def get_refer(model, multiple = False):
65
70
  module, name = model.__module__, model.__name__
66
71
  entity = '%s.%s' % (module.replace('.models', '').split('.')[-1], name)
@@ -93,6 +98,13 @@ def get_format(field):
93
98
  else:
94
99
  return {}
95
100
 
101
+ def get_field_column_width(field,clazz):
102
+ if clazz in [BooleanField, FileField, JSONField]:
103
+ return 100
104
+ elif clazz in [ DateField, DateTimeField, TimeField]:
105
+ return 120
106
+ return 0
107
+
96
108
 
97
109
 
98
110
  def load_meta_field(field):
@@ -123,6 +135,7 @@ def load_meta_field(field):
123
135
  not_null = not field.null
124
136
  align = get_align(clazz)
125
137
  _format = get_format(field)
138
+ column_width = get_field_column_width(field,clazz)
126
139
  return {
127
140
  "prop": prop,
128
141
  "label":label,
@@ -132,4 +145,5 @@ def load_meta_field(field):
132
145
  "format":_format,
133
146
  "not_null":not_null,
134
147
  "align":align,
148
+ "column_width":column_width
135
149
  }
valar/data/query.py CHANGED
@@ -1,6 +1,4 @@
1
1
  from functools import reduce
2
-
3
-
4
2
  from django.db.models import Q
5
3
 
6
4
 
@@ -17,15 +15,18 @@ class Query:
17
15
  def __init__(self, body=None):
18
16
  if body is None:
19
17
  body = {}
20
- self.template = body.get('template',{})
21
- self.condition = Condition(body.get('condition',{}))
22
- self.search = [ Condition(condition) for condition in body.get('search',[])]
23
- self.orders = body.get('orders',{})
18
+ self.template = body.get('template', {})
19
+ self.condition = Condition(body.get('condition', {}))
20
+ self.search = [Condition(condition) for condition in body.get('search', [])]
21
+ self.orders = body.get('orders', {})
22
+ self.finder = body.get('finder', {})
23
+ self.page = body.get('page',1)
24
+ self.size = body.get('size', 0)
24
25
 
25
26
  def orm_orders(self):
26
27
  array = []
27
- for key in self.orders :
28
- value = self.orders .get(key)
28
+ for key in self.orders:
29
+ value = self.orders.get(key)
29
30
  prefix = '-' if value == -1 else ''
30
31
  array.append(f'{prefix}{key}')
31
32
  return array
@@ -33,16 +34,15 @@ class Query:
33
34
  def orm_conditions(self):
34
35
  includes, excludes = self.condition.includes, self.condition.excludes
35
36
  if len(self.search):
36
- inc = [ Q(**{**includes, **sea.includes}) for sea in self.search]
37
- exc = [ Q(**{**excludes, **sea.excludes}) for sea in self.search]
38
- def fun(x, y):return x | y
37
+ inc = [Q(**{**includes, **sea.includes}) for sea in self.search]
38
+ exc = [Q(**{**excludes, **sea.excludes}) for sea in self.search]
39
+ def fun(x, y): return x | y
39
40
  return [reduce(fun, inc), reduce(fun, exc)]
40
41
  else:
41
42
  return [Q(**self.condition.includes), Q(**self.condition.excludes)]
42
43
 
43
44
  def mon_conditions(self):
44
- includes, excludes = self.condition.includes, self.condition.excludes
45
- return {}
46
-
45
+ from .mon.query_translator import MongoQueryTranslator
46
+ return MongoQueryTranslator.translate_query(self)
47
47
 
48
48
  # def _mon_conditions(self):
valar/data/urls.py CHANGED
@@ -1,15 +1,21 @@
1
- from django.urls import path
1
+ from django.urls import path, include
2
2
 
3
3
  from ..data import views
4
4
 
5
5
  urlpatterns = [
6
- path('save_one', views.save_one),
7
- path('save_many', views.save_many),
8
- path('update_many', views.update_many),
9
- path('delete_one', views.delete_one),
10
- path('delete_many', views.delete_many),
11
- path('find_one', views.find_one),
12
- path('find_many', views.find_many),
13
- path('meta', views.meta),
6
+ path('<str:db>/<str:entity>/save_one', views.save_one),
7
+ path('<str:db>/<str:entity>/save_many', views.save_many),
8
+ path('<str:db>/<str:entity>/update_many', views.update_many),
9
+ path('<str:db>/<str:entity>/delete_one', views.delete_one),
10
+ path('<str:db>/<str:entity>/delete_many', views.delete_many),
11
+ path('<str:db>/<str:entity>/find_one', views.find_one),
12
+ path('<str:db>/<str:entity>/find_many', views.find_many),
13
+ path('<str:db>/<str:entity>/tree', views.tree),
14
+
15
+ # path('data/<str:db>/<str:entity>/', include('src.valar.data.urls')),
14
16
 
17
+ path('add_fields', views.add_fields),
18
+ path('fields', views.fields),
19
+ path('meta', views.meta),
20
+ path('metas', views.metas),
15
21
  ]
valar/data/views.py CHANGED
@@ -1,5 +1,8 @@
1
1
  import json
2
2
 
3
+
4
+ from .models import MetaField, VModel
5
+ from .orm import load_model
3
6
  from .query import Query
4
7
  from .. import ValarResponse
5
8
  from ..channels import ValarSocketSender
@@ -10,12 +13,10 @@ from ..data.utils import get_dao, transform
10
13
 
11
14
 
12
15
  async def save_many(request,db, entity):
13
-
14
- data = json.loads(request.body)
15
- handler = '%s/%s' % (db, entity)
16
- sender = ValarSocketSender(handler, request)
16
+ body = json.loads(request.body)
17
+ data = body.get('data')
18
+ sender = ValarSocketSender(request)
17
19
  await execute_channel(save_many_handler, data, sender)
18
-
19
20
  return ValarResponse(True)
20
21
 
21
22
  def save_one (request,db, entity):
@@ -56,7 +57,7 @@ def find_one(request, db, entity):
56
57
 
57
58
  def find_many(request, db, entity):
58
59
  body = json.loads(request.body)
59
- query = Query(body)
60
+ query = Query(body.get('query'))
60
61
  dao = get_dao(db, entity)
61
62
  page = body.get('page', 1)
62
63
  size = body.get('size', 0)
@@ -67,10 +68,57 @@ def find_many(request, db, entity):
67
68
  'total': total
68
69
  })
69
70
 
70
- def meta(request, db, entity ):
71
+
72
+ def tree(request, db, entity):
71
73
  body = json.loads(request.body)
72
- code = body.get('code')
74
+ code = body.get('code','default')
75
+ root = body.get('root', 0)
76
+ query = Query(body)
73
77
  dao = get_dao(db, entity)
78
+ results = [n.json for n in dao.tree(query,root)]
79
+ return ValarResponse(results)
80
+
81
+
82
+ def meta(request):
83
+ body = json.loads(request.body)
84
+ code = body.get('code')
85
+ entity = body.get('entity')
86
+ dao = get_dao('orm', entity)
74
87
  view = dao.meta(code)
75
88
  return ValarResponse(view)
76
89
 
90
+ def fields(request ):
91
+ body = json.loads(request.body)
92
+ entity = body.get('entity')
93
+ dao = get_dao('orm', entity)
94
+ _fields =dao.meta_fields
95
+ return ValarResponse(_fields)
96
+
97
+
98
+
99
+ def add_fields(request):
100
+ body = json.loads(request.body)
101
+ entity = body.get('entity')
102
+ view_id = body.get('view_id')
103
+ props = body.get('props')
104
+ dao = get_dao('orm', entity)
105
+ field_dao = get_dao('orm','data.MetaField')
106
+ _fields = dao.meta_fields
107
+ for prop in props:
108
+ field = _fields.get(prop)
109
+ if field:
110
+ field['view_id'] = view_id
111
+ field_dao.save_one(field)
112
+ return ValarResponse(True)
113
+
114
+ def metas(request):
115
+ mapping = load_model()
116
+ tree = {}
117
+ for entity in mapping:
118
+ _, name = mapping[entity]
119
+ app, model = entity.split('.')
120
+ node = {'label': name, 'value': model}
121
+ root = tree.get(app, {'label': app, 'value': app, 'children': []})
122
+ root['children'].append(node)
123
+ tree[app] = root
124
+ return ValarResponse(list(tree.values()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: valar
3
- Version: 1.0.17
3
+ Version: 1.0.18
4
4
  Summary: valar for morghulis
5
5
  Author: LYP
6
6
  Author-email: liuyinpeng@buaa.edu.cn
@@ -0,0 +1,26 @@
1
+ valar/__init__.py,sha256=ekQ2XVpfTAc9RUYjriUY2On5dZBIjZGnew__TeKVWws,858
2
+ valar/channels/__init__.py,sha256=scvypQLiH-gp-Y0gZfSBAP5eoXFEyYgY7TSafzqP5Wk,3432
3
+ valar/channels/utils.py,sha256=lQQZp6XJhTHJSBvfsxgZ7PcDKYGLo5rMpWH5wtteHww,1298
4
+ valar/channels/views.py,sha256=GjcFw_WswaJnlSrv2tFx12jLk6RtzxSjW1D2kBskImY,413
5
+ valar/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ valar/data/handlers.py,sha256=2WQfJ5PJuGLPFqBpYg2my6Mh6RqAeI6jHEj4tRAsSXw,858
7
+ valar/data/models.py,sha256=jkKzxU6dqbwda_YmxiO6W7Mro_f_8lgWd3jekH1Q_FY,10495
8
+ valar/data/query.py,sha256=Cx-DDJQmMP8Qc9Sv5dvQ-QFE-aRVeYI6ccE8zUhFsVQ,1585
9
+ valar/data/urls.py,sha256=yj4BJlb0AJn6pvWSHlk-iIpDHPC0tBQzbpSop5y0on0,790
10
+ valar/data/utils.py,sha256=d5mdx_hV6Vs-SoAZLBdzQCvrbeuoXCozFzrCT-njCn0,2061
11
+ valar/data/views.py,sha256=XxbgeOX8XuENuyD4qidYlVgZyf1L4pLj52V1SNgXXDk,3426
12
+ valar/data/migrations/0001_initial.py,sha256=_990niJ2N1API1NLwffAYH_1jszdeGg0BmCAhYuEzYo,21823
13
+ valar/data/migrations/0002_valatree_alter_metafield_allow_sort.py,sha256=kmfSq_QVRAWuox9BH-vhdoO4qBEDKzHmY23dCUlrnbc,1506
14
+ valar/data/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ valar/data/mon/__init__.py,sha256=99b04h-j9HbmKlVB2qNl2ZVyUMC9pH0sofu7yXAi_Zg,3818
16
+ valar/data/mon/query_translator.py,sha256=g5rurgUOATarrO_hCuImr2VV6U1axwVSKAZx8zGeOuw,4646
17
+ valar/data/orm/__init__.py,sha256=tJxz6_oGmGoJpKNmTgDMaSf5qKO1G14j1ME0U0Lxxwk,3748
18
+ valar/data/orm/detacher.py,sha256=coZtVFzOVSl8AsoX2zLy7ZOkKVBLeg1HIKyKkstU1Tc,2660
19
+ valar/data/orm/meta.py,sha256=_difVxW-aU2kmgd3FDiuwp0Sm-T7rSwcd9STz7QLmZc,1411
20
+ valar/data/orm/meta_loader.py,sha256=LQhhMYjB1830Ee6TSRJcZtTHYmhVPGR6fxB7kwGMbtk,4863
21
+ valar/data/orm/values.py,sha256=A0g2G2_ccsIu4YjCBHV_MMeYBDvgFAmh3gKCEJ8Q9bU,4295
22
+ valar-1.0.18.dist-info/licenses/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
23
+ valar-1.0.18.dist-info/METADATA,sha256=TXlQ2p79k-2NrRcD40fhaMdOmRXyG261_Cn_G7oLZlU,2784
24
+ valar-1.0.18.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
25
+ valar-1.0.18.dist-info/top_level.txt,sha256=TVi6VcvvYfVYZ_WnUVwT4psI8p6inaP3KfmQEWrrvYg,6
26
+ valar-1.0.18.dist-info/RECORD,,