valar 0.0.11__tar.gz → 0.0.13__tar.gz

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 (33) hide show
  1. {valar-0.0.11/src/valar.egg-info → valar-0.0.13}/PKG-INFO +4 -3
  2. {valar-0.0.11 → valar-0.0.13}/README.md +1 -1
  3. {valar-0.0.11 → valar-0.0.13}/setup.py +1 -1
  4. {valar-0.0.11 → valar-0.0.13}/src/valar/__init__.py +11 -6
  5. {valar-0.0.11 → valar-0.0.13}/src/valar/channels/__init__.py +25 -23
  6. valar-0.0.11/src/valar/channels/views.py → valar-0.0.13/src/valar/channels/utils.py +14 -17
  7. valar-0.0.13/src/valar/channels/views.py +16 -0
  8. valar-0.0.13/src/valar/data/handlers.py +28 -0
  9. valar-0.0.13/src/valar/data/migrations/0001_initial.py +210 -0
  10. valar-0.0.13/src/valar/data/models.py +223 -0
  11. valar-0.0.13/src/valar/data/mon/__init__.py +84 -0
  12. valar-0.0.13/src/valar/data/orm/__init__.py +87 -0
  13. valar-0.0.13/src/valar/data/orm/detacher.py +61 -0
  14. valar-0.0.13/src/valar/data/orm/meta.py +24 -0
  15. valar-0.0.13/src/valar/data/orm/meta_loader.py +135 -0
  16. valar-0.0.13/src/valar/data/orm/values.py +93 -0
  17. valar-0.0.13/src/valar/data/query.py +48 -0
  18. valar-0.0.13/src/valar/data/urls.py +15 -0
  19. valar-0.0.13/src/valar/data/utils.py +70 -0
  20. valar-0.0.13/src/valar/data/views.py +76 -0
  21. {valar-0.0.11 → valar-0.0.13/src/valar.egg-info}/PKG-INFO +4 -3
  22. valar-0.0.13/src/valar.egg-info/SOURCES.txt +27 -0
  23. valar-0.0.11/src/valar/dao/migrations/0001_initial.py +0 -22
  24. valar-0.0.11/src/valar/dao/models.py +0 -7
  25. valar-0.0.11/src/valar/dao/views.py +0 -3
  26. valar-0.0.11/src/valar.egg-info/SOURCES.txt +0 -16
  27. {valar-0.0.11 → valar-0.0.13}/LICENSE +0 -0
  28. {valar-0.0.11 → valar-0.0.13}/setup.cfg +0 -0
  29. {valar-0.0.11/src/valar/dao → valar-0.0.13/src/valar/data}/__init__.py +0 -0
  30. {valar-0.0.11/src/valar/dao → valar-0.0.13/src/valar/data}/migrations/__init__.py +0 -0
  31. {valar-0.0.11 → valar-0.0.13}/src/valar.egg-info/dependency_links.txt +0 -0
  32. {valar-0.0.11 → valar-0.0.13}/src/valar.egg-info/requires.txt +0 -0
  33. {valar-0.0.11 → valar-0.0.13}/src/valar.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: valar
3
- Version: 0.0.11
3
+ Version: 0.0.13
4
4
  Summary: valar for morghulis
5
5
  Author: LYP
6
6
  Author-email: liuyinpeng@buaa.edu.cn
@@ -12,6 +12,7 @@ Dynamic: author
12
12
  Dynamic: author-email
13
13
  Dynamic: description
14
14
  Dynamic: description-content-type
15
+ Dynamic: license-file
15
16
  Dynamic: requires-dist
16
17
  Dynamic: requires-python
17
18
  Dynamic: summary
@@ -41,7 +42,7 @@ INSTALLED_APPS = [
41
42
  'django.contrib.sessions',
42
43
  "corsheaders",
43
44
  'channels',
44
- 'valar.dao'
45
+ 'valar.data'
45
46
  ]
46
47
 
47
48
  MIDDLEWARE = [
@@ -23,7 +23,7 @@ INSTALLED_APPS = [
23
23
  'django.contrib.sessions',
24
24
  "corsheaders",
25
25
  'channels',
26
- 'valar.dao'
26
+ 'valar.data'
27
27
  ]
28
28
 
29
29
  MIDDLEWARE = [
@@ -10,7 +10,7 @@ requires = ['channels==3.0.3']
10
10
 
11
11
  setup(
12
12
  name="valar", # 包名
13
- version="0.0.11", # 版本号
13
+ version="0.0.13", # 版本号
14
14
  author="LYP", # 作者
15
15
  author_email="liuyinpeng@buaa.edu.cn", # 邮箱
16
16
  description="valar for morghulis", # 简短描述
@@ -11,11 +11,16 @@ class ValarResponse(JsonResponse):
11
11
  class Middleware(MiddlewareMixin):
12
12
  @staticmethod
13
13
  def process_response(request: HttpRequest, response: ValarResponse):
14
- message, code = response.message, response.code
15
- user_id = request.session.get('USER_ID')
16
14
  headers = response.headers
17
- headers['valar_message'] = message
18
- headers['valar_code'] = code
19
- if user_id:
20
- headers['user_id'] = user_id
15
+ if type(response)==ValarResponse:
16
+ message, code = response.message, response.code
17
+ headers['valar_message'] = message
18
+ headers['valar_code'] = code
19
+
20
+ keys = ['client','auth','uid']
21
+ for key in keys:
22
+ value = request.headers.get(key)
23
+ if value:
24
+ headers[key] = value
25
+
21
26
  return response
@@ -1,9 +1,11 @@
1
1
  from datetime import datetime
2
2
 
3
+ from asgiref.sync import async_to_sync
3
4
  from channels.layers import get_channel_layer
4
5
 
5
- from channels.generic.websocket import AsyncJsonWebsocketConsumer
6
+ from channels.generic.websocket import AsyncJsonWebsocketConsumer, JsonWebsocketConsumer
6
7
  from django.conf import settings
8
+ from django.http import HttpRequest
7
9
 
8
10
  try:
9
11
  GROUP = settings.VALAR_CHANNEL_GROUP_NAME
@@ -11,16 +13,24 @@ except AttributeError:
11
13
  GROUP = 'VALAR'
12
14
 
13
15
  class ValarSocketSender:
14
- def __init__(self, handler: str, client: str, uid):
16
+ def __init__(self, handler: str, request: HttpRequest):
17
+ client = request.headers.get('CLIENT')
18
+ auth = request.headers.get('AUTH')
19
+ uid = request.session.get('UID')
20
+ if auth and not uid:
21
+ raise Exception('Unauthorized!')
15
22
  self.client = client
16
23
  self.uid = uid
17
24
  self.handler = handler
18
25
  self.send = get_channel_layer().group_send
19
26
 
20
- def __convert_body(self, emit, data ,clients = None, users = None):
27
+
28
+
29
+ def __convert_body(self, emit, data, status ,clients = None, users = None):
21
30
  return {
22
31
  'type': emit,
23
32
  'data': {
33
+ 'status': status,
24
34
  'handler': self.handler,
25
35
  'payload': data,
26
36
  'timestamp': datetime.now().timestamp()
@@ -30,22 +40,22 @@ class ValarSocketSender:
30
40
  }
31
41
 
32
42
 
33
- async def to_users(self, data, *users):
34
- body = self.__convert_body('user.emit', data, users=users)
35
- await self.send(GROUP, body)
43
+ def to_users(self, data, users, status='proceed'):
44
+ body = self.__convert_body(emit='user.emit', data=data, status=status, users=users)
45
+ async_to_sync(self.send)(GROUP, body)
36
46
 
37
- async def to_clients(self,data, *clients):
38
- body = self.__convert_body('client.emit', data, clients=clients)
39
- await self.send(GROUP, body)
47
+ def to_clients(self,data, clients, status='proceed'):
48
+ body = self.__convert_body(emit='client.emit', data=data, status=status, clients=clients)
49
+ async_to_sync(self.send)(GROUP, body)
40
50
 
41
- async def broadcast(self, data):
42
- body = self.__convert_body('broadcast.emit', data)
43
- await self.send(GROUP, body)
44
51
 
45
- async def register(self):
46
- body = self.__convert_body('register.emit', None,[self.client], [self.uid])
47
- await self.send(GROUP, body)
52
+ def broadcast(self, data, status):
53
+ body = self.__convert_body(emit='broadcast.emit', data=data, status=status)
54
+ async_to_sync(self.send)(GROUP, body)
48
55
 
56
+ def register(self):
57
+ body = self.__convert_body(emit='register.emit', data=None, status=None,clients=[self.client], users=[self.uid])
58
+ async_to_sync(self.send)(GROUP, body)
49
59
 
50
60
  class ValarConsumer(AsyncJsonWebsocketConsumer):
51
61
 
@@ -91,11 +101,3 @@ class ValarConsumer(AsyncJsonWebsocketConsumer):
91
101
  self.uid = users[0]
92
102
 
93
103
 
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
@@ -1,32 +1,29 @@
1
1
  import asyncio
2
+
2
3
  import importlib
3
- import json
4
4
  from django.core.exceptions import ImproperlyConfigured
5
5
  from django.conf import settings
6
6
 
7
- from .. import ValarResponse
8
- from ..channels import ValarSocketSender
9
-
10
7
 
11
8
 
12
9
 
10
+ async def execute_channel(method, data, sender):
11
+ thread = asyncio.to_thread(method, data, sender)
12
+ asyncio.create_task(thread)
13
13
 
14
- async def handel_channel(request, handler):
15
- client = request.headers.get('CLIENT')
16
- uid = request.session.get('UID')
17
- data = json.loads(request.body)
18
- method = get_valar_channel_handler(handler)
19
- sender = ValarSocketSender(handler, client, uid)
20
- if uid and client:
21
- await sender.register()
22
- loop = asyncio.get_event_loop()
23
- loop.create_task(method(data, sender))
24
- return ValarResponse({'status':'OK'})
25
14
 
26
15
 
16
+ def channel_wrapper(func):
17
+ def wrapper(*args, **kwargs):
18
+ data, sender = args
19
+ sender.to_clients(None, [sender.client],'start')
20
+ result = func(*args, **kwargs)
21
+ sender.to_clients(None, [sender.client], 'stop')
22
+ return result
23
+ return wrapper
27
24
 
28
25
 
29
- def get_valar_channel_handler(handler):
26
+ def get_channel_handler(handler):
30
27
  try:
31
28
  root = settings.VALAR_CHANNEL_HANDLER_MAPPING
32
29
  path, name = root.rsplit(".", 1)
@@ -43,4 +40,4 @@ def get_valar_channel_handler(handler):
43
40
  method = mapping[handler]
44
41
  except KeyError:
45
42
  raise ImproperlyConfigured("Cannot find handler in %r" % root)
46
- return method
43
+ return method
@@ -0,0 +1,16 @@
1
+ import json
2
+
3
+ from .utils import execute_channel, get_channel_handler
4
+ from .. import ValarResponse
5
+ from ..channels import ValarSocketSender
6
+
7
+
8
+ async def handel_channel(request, handler):
9
+ method = get_channel_handler(handler)
10
+ data = json.loads(request.body)
11
+ sender = ValarSocketSender(handler,request)
12
+ await execute_channel(method, data, sender)
13
+ return ValarResponse(True)
14
+
15
+
16
+
@@ -0,0 +1,28 @@
1
+ import time
2
+
3
+ from ..channels import ValarSocketSender
4
+ from ..channels.utils import channel_wrapper
5
+ from ..data.utils import get_dao
6
+
7
+ @channel_wrapper
8
+ def save_many_handler(data, sender: ValarSocketSender):
9
+ start_time = time.time()
10
+ entity, array, db = data.get("entity"), data.get("array",[]), data.get("db")
11
+ dao = get_dao(db, entity)
12
+ index, length = 1, len(array)
13
+ for item in array:
14
+ item['saved'] = True
15
+ dao.save_one(item)
16
+ current_time = time.time()
17
+ time_span = current_time - start_time
18
+ if time_span > 1:
19
+ start_time = current_time
20
+ send(index, length, sender)
21
+ index += 1
22
+
23
+
24
+
25
+ def send(index, length, sender):
26
+ percentage = round(index * 100 / length)
27
+ tick = {'length': length, 'index': index, 'percentage': percentage}
28
+ sender.to_clients(tick, sender.client)
@@ -0,0 +1,210 @@
1
+ # Generated by Django 5.1.7 on 2025-04-04 14:58
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='Meta',
17
+ fields=[
18
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
20
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
21
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
22
+ ('saved', models.BooleanField(default=False)),
23
+ ('entity', models.CharField(max_length=100, null=True, unique=True, verbose_name='数据源')),
24
+ ('name', models.CharField(max_length=50, null=True, verbose_name='实体别名')),
25
+ ],
26
+ options={
27
+ 'verbose_name': '数据实体',
28
+ },
29
+ ),
30
+ migrations.CreateModel(
31
+ name='MetaFieldTool',
32
+ fields=[
33
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
34
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
35
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
36
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
37
+ ('saved', models.BooleanField(default=False)),
38
+ ('pid', models.IntegerField(default=0, verbose_name='父节点')),
39
+ ('isLeaf', models.BooleanField(default=False, verbose_name='叶子节点')),
40
+ ('icon', models.CharField(max_length=255, null=True, verbose_name='图标')),
41
+ ('name', models.CharField(max_length=255, null=True, verbose_name='名称')),
42
+ ('code', models.CharField(max_length=100, null=True, unique=True, verbose_name='代码')),
43
+ ('format', models.JSONField(default=dict, verbose_name='格式参数')),
44
+ ],
45
+ options={
46
+ 'verbose_name': '元数据字段工具',
47
+ },
48
+ ),
49
+ migrations.CreateModel(
50
+ name='Vala',
51
+ fields=[
52
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
53
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
54
+ ('name', models.CharField(max_length=50, null=True)),
55
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
56
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
57
+ ('saved', models.BooleanField(default=False)),
58
+ ('text_field', models.TextField(null=True, verbose_name='text')),
59
+ ('boolean_field', models.BooleanField(null=True, verbose_name='boolean')),
60
+ ('integer_field', models.IntegerField(null=True, verbose_name='integer')),
61
+ ('float_field', models.FloatField(null=True, verbose_name='float')),
62
+ ('date_field', models.DateField(null=True, verbose_name='date')),
63
+ ('datetime_field', models.DateTimeField(null=True, verbose_name='datetime')),
64
+ ('time_field', models.TimeField(null=True, verbose_name='time')),
65
+ ('json_field', models.JSONField(null=True, verbose_name='json')),
66
+ ('file', models.FileField(null=True, upload_to='', verbose_name='File')),
67
+ ],
68
+ options={
69
+ 'abstract': False,
70
+ },
71
+ ),
72
+ migrations.CreateModel(
73
+ name='MetaFieldDomain',
74
+ fields=[
75
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
76
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
77
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
78
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
79
+ ('saved', models.BooleanField(default=False)),
80
+ ('name', models.CharField(max_length=255, null=True, unique=True, verbose_name='名称')),
81
+ ('align', models.CharField(max_length=10, null=True, verbose_name='对齐方式')),
82
+ ('default', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='data.metafieldtool', verbose_name='默认工具')),
83
+ ('search', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='data.metafieldtool', verbose_name='搜索工具')),
84
+ ('tools', models.ManyToManyField(to='data.metafieldtool', verbose_name='工具集')),
85
+ ],
86
+ options={
87
+ 'verbose_name': '元数据字段类型',
88
+ },
89
+ ),
90
+ migrations.CreateModel(
91
+ name='MetaView',
92
+ fields=[
93
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
94
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
95
+ ('name', models.CharField(max_length=50, null=True)),
96
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
97
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
98
+ ('saved', models.BooleanField(default=False)),
99
+ ('code', models.CharField(default='default ', max_length=50, verbose_name='类视图')),
100
+ ('view_name', models.CharField(max_length=50, null=True, verbose_name='视图名称')),
101
+ ('form_width', models.IntegerField(default=0, verbose_name='表单宽度')),
102
+ ('form_height', models.IntegerField(default=0, verbose_name='表单高度')),
103
+ ('table_width', models.IntegerField(default=0, verbose_name='表格宽度')),
104
+ ('table_height', models.IntegerField(default=0, verbose_name='表格高度')),
105
+ ('enable', models.BooleanField(default=True, verbose_name='是否启用')),
106
+ ('show_header', models.BooleanField(default=True, verbose_name='展示头部')),
107
+ ('allow_batch', models.BooleanField(default=True, verbose_name='批处理')),
108
+ ('allow_search', models.BooleanField(default=True, verbose_name='检索功能')),
109
+ ('allow_sort', models.BooleanField(default=True, verbose_name='排序功能')),
110
+ ('allow_pop', models.BooleanField(default=True, verbose_name='移动功能')),
111
+ ('allow_insert', models.BooleanField(default=True, verbose_name='新增功能')),
112
+ ('allow_edit', models.BooleanField(default=True, verbose_name='编辑功能')),
113
+ ('allow_remove', models.BooleanField(default=True, verbose_name='删除功能')),
114
+ ('allow_download', models.BooleanField(default=True, verbose_name='下载功能')),
115
+ ('allow_upload', models.BooleanField(default=True, verbose_name='上传功能')),
116
+ ('meta', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.meta', verbose_name='元数据')),
117
+ ],
118
+ options={
119
+ 'verbose_name': '数据视图',
120
+ 'unique_together': {('meta', 'code')},
121
+ },
122
+ ),
123
+ migrations.CreateModel(
124
+ name='MetaField',
125
+ fields=[
126
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
127
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
128
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
129
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
130
+ ('saved', models.BooleanField(default=False)),
131
+ ('prop', models.CharField(max_length=100, verbose_name='字段名称')),
132
+ ('label', models.CharField(max_length=100, verbose_name='字段标签')),
133
+ ('name', models.CharField(max_length=100, verbose_name='字段别名')),
134
+ ('domain', models.CharField(max_length=100, verbose_name='字段类型')),
135
+ ('tool', models.CharField(default='default', max_length=100, verbose_name='工具组件')),
136
+ ('refer', models.JSONField(default=dict, verbose_name='索引')),
137
+ ('format', models.JSONField(default=dict, verbose_name='格式')),
138
+ ('unit', models.CharField(max_length=55, null=True, verbose_name='单位符')),
139
+ ('not_null', models.BooleanField(default=False, verbose_name='不为空')),
140
+ ('read_only', models.BooleanField(default=False, verbose_name='只读')),
141
+ ('sortable', models.BooleanField(default=False, verbose_name='可排序')),
142
+ ('allow_search', models.BooleanField(default=True, verbose_name='可搜索')),
143
+ ('allow_download', models.BooleanField(default=True, verbose_name='可下载')),
144
+ ('allow_upload', models.BooleanField(default=False, verbose_name='可上传')),
145
+ ('allow_update', models.BooleanField(default=False, verbose_name='可更新')),
146
+ ('column_width', models.FloatField(default=0, verbose_name='表头宽度')),
147
+ ('align', models.CharField(default='left', max_length=55, verbose_name='对齐方式')),
148
+ ('fixed', models.CharField(max_length=100, null=True, verbose_name='固定位置')),
149
+ ('header_color', models.CharField(max_length=55, null=True, verbose_name='表头颜色')),
150
+ ('cell_color', models.CharField(max_length=55, null=True, verbose_name='单元颜色')),
151
+ ('edit_on_table', models.BooleanField(default=False, verbose_name='表格编辑')),
152
+ ('hide_on_table', models.BooleanField(default=False, verbose_name='表内隐藏')),
153
+ ('span', models.IntegerField(default=0, verbose_name='表单占位')),
154
+ ('hide_on_form', models.BooleanField(default=False, verbose_name='表单隐藏')),
155
+ ('hide_on_form_edit', models.BooleanField(default=False, verbose_name='编辑隐藏')),
156
+ ('hide_on_form_insert', models.BooleanField(default=False, verbose_name='新增隐藏')),
157
+ ('hide_on_form_branch', models.BooleanField(default=False, verbose_name='分支隐藏')),
158
+ ('hide_on_form_leaf', models.BooleanField(default=False, verbose_name='叶子隐藏')),
159
+ ('view', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='data.metaview', verbose_name='数据视图')),
160
+ ],
161
+ options={
162
+ 'verbose_name': '视图字段',
163
+ },
164
+ ),
165
+ migrations.CreateModel(
166
+ name='O2O',
167
+ fields=[
168
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
169
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
170
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
171
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
172
+ ('saved', models.BooleanField(default=False)),
173
+ ('name', models.CharField(max_length=100, null=True, verbose_name='name')),
174
+ ('vala', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='data.vala', verbose_name='vala')),
175
+ ],
176
+ options={
177
+ 'abstract': False,
178
+ },
179
+ ),
180
+ migrations.CreateModel(
181
+ name='M2O',
182
+ fields=[
183
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
184
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
185
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
186
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
187
+ ('saved', models.BooleanField(default=False)),
188
+ ('name', models.CharField(max_length=100, null=True, verbose_name='name')),
189
+ ('vala', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='data.vala', verbose_name='vala')),
190
+ ],
191
+ options={
192
+ 'abstract': False,
193
+ },
194
+ ),
195
+ migrations.CreateModel(
196
+ name='M2M',
197
+ fields=[
198
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
199
+ ('sort', models.BigIntegerField(null=True, verbose_name='序号')),
200
+ ('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='创建时间')),
201
+ ('modify_time', models.DateTimeField(auto_now=True, null=True, verbose_name='修改时间')),
202
+ ('saved', models.BooleanField(default=False)),
203
+ ('name', models.CharField(max_length=100, null=True, verbose_name='name')),
204
+ ('valas', models.ManyToManyField(to='data.vala', verbose_name='valas')),
205
+ ],
206
+ options={
207
+ 'abstract': False,
208
+ },
209
+ ),
210
+ ]