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

valar/data/models.py CHANGED
@@ -4,6 +4,7 @@ from django.db.models.fields.files import FieldFile
4
4
 
5
5
 
6
6
  class VModel(models.Model):
7
+ objects = models.Manager()
7
8
  sort = models.BigIntegerField(null=True, verbose_name='序号')
8
9
  name = models.CharField(max_length=50, null=True)
9
10
  create_time = models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')
@@ -180,15 +181,23 @@ class MetaFieldTool(VTree):
180
181
  verbose_name = '元数据字段工具'
181
182
  #
182
183
  #
184
+ class TestM(models.Model):
185
+ name = models.CharField(max_length=100, verbose_name='<UNK>')
186
+
183
187
  class MetaFieldDomain(VModel):
184
188
  name = models.CharField(max_length=255, unique=True, null=True, verbose_name='名称')
185
189
  tools = models.ManyToManyField(to=MetaFieldTool, verbose_name='工具集')
186
- default = models.ForeignKey(to=MetaFieldTool, null=True, on_delete=models.SET_NULL, related_name='+',
187
- verbose_name='默认工具')
188
- search = models.ForeignKey(to=MetaFieldTool, null=True, on_delete=models.SET_NULL, related_name='+',
189
- verbose_name='搜索工具')
190
+ default = models.ForeignKey(
191
+ to=MetaFieldTool, null=True,
192
+ on_delete=models.SET_NULL,
193
+ related_name='+',
194
+ verbose_name='默认工具')
195
+ search = models.ForeignKey(
196
+ to=MetaFieldTool, null=True,
197
+ on_delete=models.SET_NULL,
198
+ related_name='+',
199
+ verbose_name='搜索工具')
190
200
  align = models.CharField(max_length=10, null=True, verbose_name='对齐方式')
191
-
192
201
  class Meta:
193
202
  verbose_name = '元数据字段类型'
194
203
 
@@ -222,6 +231,6 @@ class O2O(VModel):
222
231
  name = models.CharField(max_length=100, null=True, verbose_name='name')
223
232
 
224
233
 
225
- class M2M(VModel):
234
+ class M2M(VTree):
226
235
  valas = models.ManyToManyField(to=Vala, verbose_name='valas')
227
236
  name = models.CharField(max_length=100, null=True, verbose_name='name')
@@ -1,14 +1,18 @@
1
1
  import datetime
2
2
  from django.apps import apps
3
3
  from django.core.paginator import Paginator
4
- from django.db.models import Manager, QuerySet
4
+ from django.db.models import Manager, QuerySet, FileField
5
5
 
6
+ from .meta_frame import load_meta_frame
7
+ from ..file import minio_remove_path
6
8
  from ..orm.detacher import detach_props, save_detached
7
9
  from ..orm.meta_loader import load_meta, load_view, load_meta_field
8
- from ..models import VModel
10
+ from ..models import VModel, VTree
9
11
  from ..query import Query
10
12
 
11
13
 
14
+ load_meta_frame()
15
+
12
16
  def load_model(entity=None):
13
17
  mapping = {}
14
18
  for mod in apps.get_models():
@@ -31,12 +35,13 @@ class OrmDao:
31
35
  if param is None:
32
36
  raise Exception('no entity named %s' % entity)
33
37
  self.model = param[0]
38
+ self.isTree = issubclass(self.model, VTree)
34
39
  self.name: str = param[1]
35
40
  self.manager: Manager = self.model.objects
36
41
  self.meta_fields = {}
37
42
  self.model_fields = {}
38
43
  for field in self.model._meta.get_fields():
39
- _field = load_meta_field(field)
44
+ _field = load_meta_field(field, self.isTree)
40
45
  prop = _field['prop']
41
46
  self.model_fields[prop] = field
42
47
  self.meta_fields[prop] = _field
@@ -45,7 +50,6 @@ class OrmDao:
45
50
  def tree(self, query: Query, root_id = 0):
46
51
  all_set, _ = self.find_many(Query())
47
52
  includes, excludes = query.orm_conditions()
48
- print(root_id)
49
53
  if not len(includes) + len(excludes) + root_id:
50
54
  return all_set
51
55
  values = all_set.values('id','pid')
@@ -62,6 +66,19 @@ class OrmDao:
62
66
  id_set.update(route)
63
67
  return all_set.filter(id__in=id_set).order_by('-sort')
64
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
+
65
82
  def save_one(self, item):
66
83
  _item = detach_props(item, self.meta_fields.values())
67
84
  _id = item.get('id',0)
@@ -69,6 +86,7 @@ class OrmDao:
69
86
  if len(query_set):
70
87
  del item['id']
71
88
  item['modify_time'] = datetime.datetime.now()
89
+ self.__check_remove_file__(query_set,item)
72
90
  query_set.update(**item)
73
91
  bean = query_set.first()
74
92
  else:
@@ -79,13 +97,18 @@ class OrmDao:
79
97
  return bean
80
98
 
81
99
  def update_many(self, query: Query, template):
82
- self.find_many(query).update(**template)
100
+ query_set, total = self.find_many(query)
101
+ query_set.update(**template)
83
102
 
84
103
  def delete_one(self, _id):
85
- self.manager.filter(id=_id).delete()
104
+ query_set = self.manager.filter(id=_id)
105
+ self.__check_remove_file__(query_set)
106
+ query_set.delete()
86
107
 
87
108
  def delete_many(self, query: Query):
88
- self.find_many(query)[0].delete()
109
+ query_set, total = self.find_many(query)
110
+ self.__check_remove_file__(query_set)
111
+ query_set.delete()
89
112
 
90
113
  def find_one(self, _id):
91
114
  return self.manager.filter(id=_id).first()
@@ -104,7 +127,9 @@ class OrmDao:
104
127
  omit = [ 'id', 'saved', 'sort', 'create_time', 'modify_time']
105
128
  fields = [ self.meta_fields[prop] for prop in self.meta_fields if prop not in omit]
106
129
  view = load_view(self.entity, code, self.name, fields)
107
- return load_meta(view)
130
+ _view = load_meta(view)
131
+ _view['isTree'] = self.isTree
132
+ return _view
108
133
 
109
134
 
110
135
 
valar/data/orm/meta.py CHANGED
@@ -1,4 +1,4 @@
1
- mf_common = ['prop','name','domain']
1
+ mf_common = ['prop','name']
2
2
 
3
3
  meta_props = {
4
4
  'data.Meta': {
@@ -8,8 +8,8 @@ meta_props = {
8
8
  'list': ('pick', ['meta_id','code','view_name']),
9
9
  },
10
10
  'data.MetaField': {
11
- 'add': ('pick',[*mf_common]),
12
- 'tool': ('pick',[*mf_common,'tool','refer','format']),
11
+ 'add': ('pick',['prop','domain','name']),
12
+ 'tool': ('pick',[*mf_common,'domain','tool','refer','format']),
13
13
  'rest': ('pick',[*mf_common,'not_null','allow_edit','allow_sort','allow_search','allow_download','allow_upload','allow_update']),
14
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']),
@@ -18,17 +18,70 @@ meta_props = {
18
18
 
19
19
 
20
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
+ },
21
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
+ },
22
68
  "prop":{
23
69
  'allow_edit': False,
24
- 'column_width': 100
70
+ 'column_width': 120
25
71
  },
26
72
  "domain":{
27
73
  'allow_edit': False,
28
- 'column_width': 100
74
+ 'column_width': 120,
29
75
  },
30
76
  "tool":{
31
- 'column_width': 100
77
+ 'column_width': 100,
78
+ 'tool': 'tree',
79
+ 'refer': {
80
+ 'entity':'data.MetaFieldTool',
81
+ 'includes': {'metafielddomain__name':'$domain'},
82
+ 'value': 'code'
83
+ }
84
+
32
85
  },
33
86
  "span":{
34
87
  'column_width': 100,
@@ -0,0 +1,49 @@
1
+ import os
2
+
3
+ from django.db import OperationalError
4
+
5
+ from src.valar.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
+
@@ -2,16 +2,17 @@ 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 .meta_frame import convert_meta_fields
5
6
  from ..orm.meta import meta_props, meta_defaults
6
- from ..models import Meta, MetaView, VModel, MetaField
7
-
8
-
7
+ from ..models import Meta, MetaView, VModel, MetaField, VTree
9
8
 
9
+ from deepmerge import always_merger
10
10
 
11
11
 
12
12
  def __save_model(model):
13
13
  model.save()
14
14
  model.sort = model.id
15
+ model.saved = True
15
16
  model.save()
16
17
 
17
18
 
@@ -31,8 +32,7 @@ def load_view(entity, code, name, fields):
31
32
  defaults = meta_defaults.get(entity,{})
32
33
  for _field in _fields:
33
34
  prop = _field['prop']
34
- _field.update(defaults.get(prop,{}))
35
-
35
+ _field = always_merger.merge(_field,defaults.get(prop,{}))
36
36
  _fields.reverse()
37
37
  for f in _fields:
38
38
  f['view'] = view
@@ -44,7 +44,8 @@ def load_meta(view):
44
44
  _view = view.full
45
45
  _meta = _view['meta']
46
46
  fields = view.metafield_set.all().order_by('-sort')
47
- _fields = [f.json for f in fields]
47
+ _fields = convert_meta_fields(fields,_meta['entity'])
48
+ # _fields = [f.json for f in fields]
48
49
  clear_item(_view, 'meta_id', 'metafield', 'metafield_set', 'meta')
49
50
  _view['meta_name'] = _meta['name']
50
51
  _view['entity'] = _meta['entity']
@@ -66,6 +67,15 @@ def clear_item(item, *keys):
66
67
  del item[key]
67
68
 
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
+
69
79
  def get_refer(model, multiple = False):
70
80
  module, name = model.__module__, model.__name__
71
81
  entity = '%s.%s' % (module.replace('.models', '').split('.')[-1], name)
@@ -73,30 +83,61 @@ def get_refer(model, multiple = False):
73
83
  "entity": entity,
74
84
  "value": "id", "label": 'name', "display": "id",
75
85
  "strict": False, "remote": False, "multiple": multiple,
76
- "includes": {}, "excludes": {}, "root": 0,
86
+ "includes": {}, "excludes": {}, "root": 0, "isTree": issubclass(model, VTree)
77
87
  }
78
88
 
79
89
  def get_align(clazz):
80
- if clazz in [FloatField, IntegerField, ManyToManyRel, ManyToManyField, ManyToOneRel]:
90
+ if clazz in [FloatField, IntegerField]: #, ManyToManyRel, ManyToManyField, ManyToOneRel
81
91
  return 'right'
82
92
  elif clazz in [BooleanField,FileField,JSONField,DateField,DateTimeField,TimeField]:
83
93
  return 'center'
84
94
  return 'left'
85
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
+
86
126
  def get_format(field):
87
127
  clazz = type(field)
128
+ _format = get_default_format()
88
129
  if clazz == CharField:
89
- return {'maxlength': field.max_length, "type": "text"}
130
+ _format['maxlength'] = field.max_length
90
131
  if clazz == TextField:
91
- return {'maxlength': None, "type": "textarea"}
92
- elif clazz == FloatField:
93
- return {'min': None, 'max': None, 'step': 1, 'precision': None, 'step_strictly': False}
132
+ _format['type'] = "textarea"
133
+ elif clazz == DateTimeField:
134
+ _format['frequency'] = "datetime"
94
135
  elif clazz == IntegerField:
95
- return {'min': None, 'max': None, 'step': 1, 'precision': 0, 'step_strictly': True}
136
+ _format['precision'] = 0
137
+ _format['step_strictly'] = True
96
138
  elif clazz == FileField:
97
- return {'max': 5, 'accept': "*", "width": "800px", "height": "auto", 'locked': False}
98
- else:
99
- return {}
139
+ pass
140
+ return _format
100
141
 
101
142
  def get_field_column_width(field,clazz):
102
143
  if clazz in [BooleanField, FileField, JSONField]:
@@ -107,7 +148,7 @@ def get_field_column_width(field,clazz):
107
148
 
108
149
 
109
150
 
110
- def load_meta_field(field):
151
+ def load_meta_field(field, isTree):
111
152
  clazz = type(field)
112
153
  if clazz in [ManyToOneRel, ManyToManyField, ManyToManyRel]:
113
154
  prop = field.name
@@ -131,12 +172,12 @@ def load_meta_field(field):
131
172
  prop = field.name
132
173
  domain = field.get_internal_type()
133
174
  label = field.verbose_name
134
- refer = {}
175
+ refer = get_default_refer()
135
176
  not_null = not field.null
136
177
  align = get_align(clazz)
137
178
  _format = get_format(field)
138
179
  column_width = get_field_column_width(field,clazz)
139
- return {
180
+ _field = {
140
181
  "prop": prop,
141
182
  "label":label,
142
183
  "name":label,
@@ -147,3 +188,13 @@ def load_meta_field(field):
147
188
  "align":align,
148
189
  "column_width":column_width
149
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
valar/data/orm/values.py CHANGED
@@ -43,6 +43,13 @@ def get_props(model:VModel, code):
43
43
  return simple_props, referred_fields, date_props
44
44
 
45
45
 
46
+ def __get_ref_keys__(related_model):
47
+ """新增功能"""
48
+ return [f.name for f in related_model._meta.get_fields()
49
+ if type(f) not in [ManyToManyField, ManyToOneRel, ManyToManyRel, ForeignKey, OneToOneField, OneToOneRel]
50
+ and f.name not in ['create_time', 'modify_time', 'saved', 'sort']
51
+ ]
52
+
46
53
  def to_dict(query_set: QuerySet, code=None):
47
54
  model = query_set.model
48
55
  simple_props, referred_fields, date_props = get_props(model, code)
@@ -62,8 +69,9 @@ def to_dict(query_set: QuerySet, code=None):
62
69
  keys = {'id', value, display, label}
63
70
  if clazz in [ForeignKey, OneToOneField, OneToOneRel]:
64
71
  related_model = field.related_model
72
+ __keys = __get_ref_keys__(related_model)
65
73
  related_pks = set([row.get(prop) for row in results if row.get(prop)])
66
- related_items = related_model.objects.filter(id__in=related_pks).values(*keys)
74
+ related_items = related_model.objects.filter(id__in=related_pks).values(*__keys)
67
75
  mapping = {item['id']: item for item in related_items}
68
76
  for row in results:
69
77
  value = row.get(prop)
@@ -82,7 +90,8 @@ def to_dict(query_set: QuerySet, code=None):
82
90
  array.append(_pk)
83
91
  row_mapping[_id] = array
84
92
  related_model = field.related_model
85
- related_items = related_model.objects.filter(id__in=_pks).values(*keys)
93
+ __keys = __get_ref_keys__(related_model)
94
+ related_items = related_model.objects.filter(id__in=_pks).values(*__keys)
86
95
  mapping = {item['id']: item for item in related_items}
87
96
  for row in results:
88
97
  _id = row.get('id')
valar/data/urls.py CHANGED
@@ -5,11 +5,14 @@ from ..data import views
5
5
  urlpatterns = [
6
6
  path('<str:db>/<str:entity>/save_one', views.save_one),
7
7
  path('<str:db>/<str:entity>/save_many', views.save_many),
8
+ path('<str:db>/<str:entity>/save_file', views.save_file),
9
+
8
10
  path('<str:db>/<str:entity>/update_many', views.update_many),
9
11
  path('<str:db>/<str:entity>/delete_one', views.delete_one),
10
12
  path('<str:db>/<str:entity>/delete_many', views.delete_many),
11
13
  path('<str:db>/<str:entity>/find_one', views.find_one),
12
14
  path('<str:db>/<str:entity>/find_many', views.find_many),
15
+ path('find_file/<str:bucket_name>/<str:object_name>', views.find_file),
13
16
  path('<str:db>/<str:entity>/tree', views.tree),
14
17
 
15
18
  # path('data/<str:db>/<str:entity>/', include('src.valar.data.urls')),
valar/data/views.py CHANGED
@@ -1,7 +1,14 @@
1
1
  import json
2
+ from io import BytesIO
2
3
 
4
+ from django.core.files.uploadedfile import InMemoryUploadedFile
5
+ from django.http import QueryDict, HttpResponse
6
+ from django.utils.encoding import escape_uri_path
7
+ from urllib3 import HTTPResponse
3
8
 
4
- from .models import MetaField, VModel
9
+ from .file import get_minio_object_name, get_minio_bucket_name, minio_upload_object, minio_remove_path, \
10
+ minio_read_object
11
+ from .models import MetaField, VModel, VTree
5
12
  from .orm import load_model
6
13
  from .query import Query
7
14
  from .. import ValarResponse
@@ -59,10 +66,8 @@ def find_many(request, db, entity):
59
66
  body = json.loads(request.body)
60
67
  query = Query(body.get('query'))
61
68
  dao = get_dao(db, entity)
62
- page = body.get('page', 1)
63
- size = body.get('size', 0)
64
69
  code = body.get('code')
65
- results, total = dao.find_many(query, size, page)
70
+ results, total = dao.find_many(query, query.size, query.page)
66
71
  return ValarResponse({
67
72
  'results': transform(db, results, code),
68
73
  'total': total
@@ -71,7 +76,6 @@ def find_many(request, db, entity):
71
76
 
72
77
  def tree(request, db, entity):
73
78
  body = json.loads(request.body)
74
- code = body.get('code','default')
75
79
  root = body.get('root', 0)
76
80
  query = Query(body)
77
81
  dao = get_dao(db, entity)
@@ -117,8 +121,53 @@ def metas(request):
117
121
  for entity in mapping:
118
122
  _, name = mapping[entity]
119
123
  app, model = entity.split('.')
120
- node = {'label': name, 'value': model}
124
+ node = {'label': name, 'value': model, 'isTree': issubclass(_, VTree)}
121
125
  root = tree.get(app, {'label': app, 'value': app, 'children': []})
122
126
  root['children'].append(node)
123
127
  tree[app] = root
124
- return ValarResponse(list(tree.values()))
128
+ return ValarResponse(list(tree.values()))
129
+
130
+ def find_file(request, bucket_name, object_name):
131
+ print(bucket_name, object_name)
132
+ ret: HTTPResponse = minio_read_object(bucket_name, object_name)
133
+ file_bytes = BytesIO(ret.read())
134
+ content = file_bytes
135
+ response = HttpResponse(content)
136
+ response['Content-Type'] = 'application/octet-stream;charset=utf-8'
137
+ response['Content-Disposition'] = "attachment; filename={}".format(escape_uri_path(object_name))
138
+
139
+ return response
140
+
141
+ def save_file(request, db, entity):
142
+ params: QueryDict = request.POST.dict()
143
+ _id, prop, field = (params.get(key) for key in ['id','prop','field'])
144
+ file: InMemoryUploadedFile = request.FILES['file']
145
+ dao = get_dao(db, entity)
146
+ item = dao.find_one(params.get('id',0))
147
+ if item:
148
+ """删除已有文件"""
149
+ old_value = getattr(item, prop)
150
+ if old_value:
151
+ minio_remove_path(old_value.name)
152
+ """上传新文件"""
153
+ bucket_name = get_minio_bucket_name(entity)
154
+ object_name = get_minio_object_name(_id, prop, file.name)
155
+ path = minio_upload_object(bucket_name, object_name, file.read())
156
+ """更新数据"""
157
+ setattr(item, prop, path)
158
+ if field:
159
+ setattr(item, field, file.name)
160
+ item.save()
161
+ return ValarResponse({
162
+ 'uploaded': True,
163
+ "url": f'/files/{path}',
164
+ 'fileName': path,
165
+ "name": file.name
166
+ })
167
+ else:
168
+ return ValarResponse(False)
169
+
170
+ # path = service.save_file(domain, entity, item, prop, file)
171
+ # dfs.remove_path(old_path)
172
+
173
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: valar
3
- Version: 1.0.18
3
+ Version: 1.0.19
4
4
  Summary: valar for morghulis
5
5
  Author: LYP
6
6
  Author-email: liuyinpeng@buaa.edu.cn
@@ -11,6 +11,10 @@ Requires-Dist: channels==3.0.3
11
11
  Requires-Dist: pymongo~=4.11.2
12
12
  Requires-Dist: asgiref~=3.8.1
13
13
  Requires-Dist: django-cors-headers==4.2.0
14
+ Requires-Dist: pandas==2.2.3
15
+ Requires-Dist: openpyxl==3.1.5
16
+ Requires-Dist: deepmerge~=2.0
17
+ Requires-Dist: minio==7.2.2
14
18
  Dynamic: author
15
19
  Dynamic: author-email
16
20
  Dynamic: description
@@ -0,0 +1,27 @@
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=XXKT1DXcAQCv8mTKWB8AP7zO6Bt0RB9QQosmJ7vUT6Q,10621
8
+ valar/data/query.py,sha256=Cx-DDJQmMP8Qc9Sv5dvQ-QFE-aRVeYI6ccE8zUhFsVQ,1585
9
+ valar/data/urls.py,sha256=32EqAi4A2zR-_-FE3Ued8gVetHuY3hdgausP7eIFL3w,929
10
+ valar/data/utils.py,sha256=d5mdx_hV6Vs-SoAZLBdzQCvrbeuoXCozFzrCT-njCn0,2061
11
+ valar/data/views.py,sha256=wiKBRsrBDT4arusLh9NKBgZFK7lwaTgsTZiuTnNsJFQ,5292
12
+ valar/data/file/__init__.py,sha256=YwBQ0Vhfg3wbcCa6k57c9vL-AnpOgnDO6lInERlIyPc,2880
13
+ valar/data/migrations/0001_initial.py,sha256=jBWKQwSclN8NctNIctqied1ibVYMEXUyimzQICLMJEA,15681
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=beQOUIDMEx83sMERr4NtZikgGxjhEDUJReYz4x8Zf7E,4730
18
+ valar/data/orm/detacher.py,sha256=coZtVFzOVSl8AsoX2zLy7ZOkKVBLeg1HIKyKkstU1Tc,2660
19
+ valar/data/orm/meta.py,sha256=gzrqBp6VEryIApu1Ab3WxLRtXXcnGJ7O9UlCSjElYcw,2719
20
+ valar/data/orm/meta_frame.py,sha256=63mKMHw6lGVAq_R2Ml-KG3Xstd8s1Rxv2e9xDAazeRg,1538
21
+ valar/data/orm/meta_loader.py,sha256=aAOtZSkIONT85tld9UxK2FFClltnyZ0zJZAeyrTU1-A,6031
22
+ valar/data/orm/values.py,sha256=5B4zpxhW9tplz4qPaNx5ONzYt5JosS0_K4XfDUQKD38,4716
23
+ valar-1.0.19.dist-info/licenses/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
24
+ valar-1.0.19.dist-info/METADATA,sha256=cauwp8rZdtCogK5NpMyy2ZuZTctGHegNubueoJv4JsY,2902
25
+ valar-1.0.19.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
26
+ valar-1.0.19.dist-info/top_level.txt,sha256=TVi6VcvvYfVYZ_WnUVwT4psI8p6inaP3KfmQEWrrvYg,6
27
+ valar-1.0.19.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5