Merge branch 'temp' into treebeard

treebeard
Angelo 2022-05-18 18:03:19 +08:00
commit d6f8c707a1
11 changed files with 1058 additions and 672 deletions

View File

@ -10,7 +10,7 @@ def is_tenants_mode():
判断是否为租户模式
:return:
"""
return hasattr(connection, 'tenant') and connection.tenant.schema_name
return hasattr(connection, "tenant") and connection.tenant.schema_name
# ================================================= #
@ -18,27 +18,37 @@ def is_tenants_mode():
# ================================================= #
def _get_all_dictionary():
from dvadmin.system.models import Dictionary
queryset = Dictionary.objects.filter(status=True, is_value=False)
data = []
for instance in queryset:
data.append({
data.append(
{
"id": instance.id,
"value": instance.value,
"children": list(Dictionary.objects.filter(parent=instance.id).filter(status=1).
values('label', 'value', 'type', 'color'))
})
"children": list(
instance.get_children()
.filter(status=1)
.values("label", "value", "type", "color")
),
}
)
return {ele.get("value"): ele for ele in data}
def _get_all_system_config():
data = {}
from dvadmin.system.models import SystemConfig
system_config_obj = SystemConfig.objects.filter(status=True, parent_id__isnull=False).values(
'parent__key', 'key', 'value', 'form_item_type').order_by('sort')
system_config_obj = (
SystemConfig.objects.filter(status=True, parent__isnull=False)
.values("parent__key", "key", "value", "form_item_type")
.order_by("sort")
)
for system_config in system_config_obj:
value = system_config.get('value') or ''
if value and system_config.get('form_item_type') == 7:
value = value[0].get('url')
value = system_config.get("value") or ""
if value and system_config.get("form_item_type") == 7:
value = value[0].get("url")
data[f"{system_config.get('parent__key')}.{system_config.get('key')}"] = value
return data
@ -51,9 +61,12 @@ def init_dictionary():
try:
if is_tenants_mode():
from django_tenants.utils import tenant_context, get_tenant_model
for tenant in get_tenant_model().objects.filter():
with tenant_context(tenant):
settings.DICTIONARY_CONFIG[connection.tenant.schema_name] = _get_all_dictionary()
settings.DICTIONARY_CONFIG[
connection.tenant.schema_name
] = _get_all_dictionary()
else:
settings.DICTIONARY_CONFIG = _get_all_dictionary()
print("初始化字典配置完成")
@ -72,9 +85,12 @@ def init_system_config():
if is_tenants_mode():
from django_tenants.utils import tenant_context, get_tenant_model
for tenant in get_tenant_model().objects.filter():
with tenant_context(tenant):
settings.SYSTEM_CONFIG[connection.tenant.schema_name] = _get_all_system_config()
settings.SYSTEM_CONFIG[
connection.tenant.schema_name
] = _get_all_system_config()
else:
settings.SYSTEM_CONFIG = _get_all_system_config()
print("初始化系统配置完成")
@ -90,9 +106,12 @@ def refresh_dictionary():
"""
if is_tenants_mode():
from django_tenants.utils import tenant_context, get_tenant_model
for tenant in get_tenant_model().objects.filter():
with tenant_context(tenant):
settings.DICTIONARY_CONFIG[connection.tenant.schema_name] = _get_all_dictionary()
settings.DICTIONARY_CONFIG[
connection.tenant.schema_name
] = _get_all_dictionary()
else:
settings.DICTIONARY_CONFIG = _get_all_dictionary()
@ -104,9 +123,12 @@ def refresh_system_config():
"""
if is_tenants_mode():
from django_tenants.utils import tenant_context, get_tenant_model
for tenant in get_tenant_model().objects.filter():
with tenant_context(tenant):
settings.SYSTEM_CONFIG[connection.tenant.schema_name] = _get_all_system_config()
settings.SYSTEM_CONFIG[
connection.tenant.schema_name
] = _get_all_system_config()
else:
settings.SYSTEM_CONFIG = _get_all_system_config()
@ -121,7 +143,9 @@ def get_dictionary_config(schema_name=None):
:return:
"""
if is_tenants_mode():
dictionary_config = settings.DICTIONARY_CONFIG[schema_name or connection.tenant.schema_name]
dictionary_config = settings.DICTIONARY_CONFIG[
schema_name or connection.tenant.schema_name
]
else:
dictionary_config = settings.DICTIONARY_CONFIG
return dictionary_config or {}
@ -165,7 +189,9 @@ def get_system_config(schema_name=None):
:return:
"""
if is_tenants_mode():
dictionary_config = settings.SYSTEM_CONFIG[schema_name or connection.tenant.schema_name]
dictionary_config = settings.SYSTEM_CONFIG[
schema_name or connection.tenant.schema_name
]
else:
dictionary_config = settings.SYSTEM_CONFIG
return dictionary_config or {}

19
backend/dev/_venv.py Normal file
View File

@ -0,0 +1,19 @@
import os
import sys
from pathlib import Path
# #################### start #######################
# AREPL for python调试导入项目依赖 (可禁用)
BASE_DIR = Path(__file__).parent.parent
VENV_DIR = Path.joinpath(BASE_DIR, "__pypackages__", "3.8", "lib") # PDM
# print(f"{BASE_DIR=}")
# 确认BASE_DIR无误后添加如下路径至系统路径
for dir in [str(BASE_DIR), str(VENV_DIR)]:
if dir not in sys.path:
sys.path.insert(1, dir)
# #################### end #########################
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
django.setup()

View File

@ -1,6 +1,9 @@
import hashlib
import os
from treebeard.mp_tree import MP_Node
from treebeard.al_tree import AL_Node
from django.contrib.auth.models import AbstractUser
from django.db import models
@ -14,62 +17,107 @@ STATUS_CHOICES = (
class Users(AbstractUser, CoreModel):
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号', help_text="用户账号")
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
username = models.CharField(
max_length=150,
unique=True,
db_index=True,
verbose_name="用户账号",
help_text="用户账号",
)
email = models.EmailField(
max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱"
)
mobile = models.CharField(
max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话"
)
avatar = models.CharField(
max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像"
)
name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")
GENDER_CHOICES = (
(0, "未知"),
(1, ""),
(2, ""),
)
gender = models.IntegerField(choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True,
help_text="性别")
gender = models.IntegerField(
choices=GENDER_CHOICES,
default=0,
verbose_name="性别",
null=True,
blank=True,
help_text="性别",
)
USER_TYPE = (
(0, "后台用户"),
(1, "前台用户"),
)
user_type = models.IntegerField(choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True,
help_text="用户类型")
post = models.ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False, help_text="关联岗位")
role = models.ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False, help_text="关联角色")
dept = models.ForeignKey(to='Dept', verbose_name='所属部门', on_delete=models.PROTECT, db_constraint=False, null=True,
blank=True, help_text="关联部门")
user_type = models.IntegerField(
choices=USER_TYPE,
default=0,
verbose_name="用户类型",
null=True,
blank=True,
help_text="用户类型",
)
post = models.ManyToManyField(
to="Post", verbose_name="关联岗位", db_constraint=False, help_text="关联岗位"
)
role = models.ManyToManyField(
to="Role", verbose_name="关联角色", db_constraint=False, help_text="关联角色"
)
dept = models.ForeignKey(
to="Dept",
verbose_name="所属部门",
on_delete=models.PROTECT,
db_constraint=False,
null=True,
blank=True,
help_text="关联部门",
)
def set_password(self, raw_password):
super().set_password(hashlib.md5(raw_password.encode(encoding='UTF-8')).hexdigest())
super().set_password(
hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest()
)
class Meta:
db_table = table_prefix + "system_users"
verbose_name = '用户表'
verbose_name = "用户表"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
ordering = ("-create_datetime",)
class Post(CoreModel):
name = models.CharField(null=False, max_length=64, verbose_name="岗位名称", help_text="岗位名称")
name = models.CharField(
null=False, max_length=64, verbose_name="岗位名称", help_text="岗位名称"
)
code = models.CharField(max_length=32, verbose_name="岗位编码", help_text="岗位编码")
sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")
STATUS_CHOICES = (
(0, "离职"),
(1, "在职"),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name="岗位状态", help_text="岗位状态")
status = models.IntegerField(
choices=STATUS_CHOICES, default=1, verbose_name="岗位状态", help_text="岗位状态"
)
class Meta:
db_table = table_prefix + "system_post"
verbose_name = '岗位表'
verbose_name = "岗位表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
class Role(CoreModel):
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
key = models.CharField(max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符")
key = models.CharField(
max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符"
)
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态")
admin = models.BooleanField(default=False, verbose_name="是否为admin", help_text="是否为admin")
admin = models.BooleanField(
default=False, verbose_name="是否为admin", help_text="是否为admin"
)
DATASCOPE_CHOICES = (
(0, "仅本人数据权限"),
(1, "本部门及以下数据权限"),
@ -77,67 +125,119 @@ class Role(CoreModel):
(3, "全部数据权限"),
(4, "自定数据权限"),
)
data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围")
data_range = models.IntegerField(
default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围"
)
remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
dept = models.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False, help_text="数据权限-关联部门")
menu = models.ManyToManyField(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text="关联菜单")
permission = models.ManyToManyField(to='MenuButton', verbose_name='关联菜单的接口按钮', db_constraint=False,
help_text="关联菜单的接口按钮")
dept = models.ManyToManyField(
to="Dept", verbose_name="数据权限-关联部门", db_constraint=False, help_text="数据权限-关联部门"
)
menu = models.ManyToManyField(
to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单"
)
permission = models.ManyToManyField(
to="MenuButton",
verbose_name="关联菜单的接口按钮",
db_constraint=False,
help_text="关联菜单的接口按钮",
)
class Meta:
db_table = table_prefix + 'system_role'
verbose_name = '角色表'
db_table = table_prefix + "system_role"
verbose_name = "角色表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
class Dept(CoreModel):
class Dept(AL_Node, CoreModel):
name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称")
sort = models.IntegerField(default=1, verbose_name="显示排序", help_text="显示排序")
owner = models.CharField(max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人")
phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")
email = models.EmailField(max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
status = models.BooleanField(default=True, verbose_name="部门状态", null=True, blank=True,
help_text="部门状态")
parent = models.ForeignKey(to='Dept', on_delete=models.CASCADE, default=None, verbose_name="上级部门",
db_constraint=False, null=True, blank=True, help_text="上级部门")
owner = models.CharField(
max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人"
)
phone = models.CharField(
max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话"
)
email = models.EmailField(
max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱"
)
status = models.BooleanField(
default=True, verbose_name="部门状态", null=True, blank=True, help_text="部门状态"
)
parent = models.ForeignKey(
to="Dept",
on_delete=models.CASCADE,
default=None,
verbose_name="上级部门",
db_constraint=False,
null=True,
blank=True,
help_text="上级部门",
)
node_order_by = ["sort", "name"]
class Meta:
db_table = table_prefix + "system_dept"
verbose_name = '部门表'
verbose_name = "部门表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
class Menu(CoreModel):
parent = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name="上级菜单", null=True, blank=True,
db_constraint=False, help_text="上级菜单")
icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标")
class Menu(MP_Node, CoreModel):
icon = models.CharField(
max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标"
)
name = models.CharField(max_length=64, verbose_name="菜单名称", help_text="菜单名称")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
sort = models.IntegerField(
default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序"
)
ISLINK_CHOICES = (
(0, ""),
(1, ""),
)
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")
component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True, help_text="组件名称")
status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示", help_text="侧边栏中是否显示")
is_catalog = models.BooleanField(
default=False, verbose_name="是否目录", help_text="是否目录"
)
web_path = models.CharField(
max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址"
)
component = models.CharField(
max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址"
)
component_name = models.CharField(
max_length=50, verbose_name="组件名称", null=True, blank=True, help_text="组件名称"
)
status = models.BooleanField(
default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态"
)
cache = models.BooleanField(
default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存"
)
visible = models.BooleanField(
default=True, blank=True, verbose_name="侧边栏中是否显示", help_text="侧边栏中是否显示"
)
def __str__(self) -> str:
return self.name
class Meta:
db_table = table_prefix + "system_menu"
verbose_name = '菜单表'
verbose_name = "菜单表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
class MenuButton(CoreModel):
menu = models.ForeignKey(to="Menu", db_constraint=False, related_name="menuPermission", on_delete=models.CASCADE,
verbose_name="关联菜单", help_text='关联菜单')
menu = models.ForeignKey(
to="Menu",
db_constraint=False,
related_name="menuPermission",
on_delete=models.CASCADE,
verbose_name="关联菜单",
help_text="关联菜单",
)
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值")
api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")
@ -147,78 +247,121 @@ class MenuButton(CoreModel):
(2, "PUT"),
(3, "DELETE"),
)
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
method = models.IntegerField(
default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法"
)
class Meta:
db_table = table_prefix + "system_menu_button"
verbose_name = '菜单权限表'
verbose_name = "菜单权限表"
verbose_name_plural = verbose_name
ordering = ('-name',)
ordering = ("-name",)
class Dictionary(CoreModel):
class Dictionary(MP_Node, CoreModel):
TYPE_LIST = (
(0, 'text'),
(1, 'number'),
(2, 'date'),
(3, 'datetime'),
(4, 'time'),
(5, 'files'),
(6, 'boolean'),
(7, 'images'),
(0, "text"),
(1, "number"),
(2, "date"),
(3, "datetime"),
(4, "time"),
(5, "files"),
(6, "boolean"),
(7, "images"),
)
label = models.CharField(
max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称"
)
value = models.CharField(
max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值"
)
type = models.IntegerField(
choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型"
)
color = models.CharField(
max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色"
)
is_value = models.BooleanField(
default=False, verbose_name="是否为value值", help_text="是否为value值,用来做具体值存放"
)
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值")
parent = models.ForeignKey(to='self', related_name='sublist', db_constraint=False, on_delete=models.PROTECT,
blank=True, null=True, verbose_name="父级", help_text="父级")
type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型")
color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色")
is_value = models.BooleanField(default=False, verbose_name="是否为value值", help_text="是否为value值,用来做具体值存放")
status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
sort = models.IntegerField(
default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序"
)
remark = models.CharField(
max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注"
)
def __str__(self) -> str:
return self.label
class Meta:
db_table = table_prefix + 'system_dictionary'
db_table = table_prefix + "system_dictionary"
verbose_name = "字典表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
super().save(force_insert, force_update, using, update_fields)
dispatch.refresh_dictionary() # 有更新则刷新字典配置
class OperationLog(CoreModel):
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址")
request_body = models.TextField(verbose_name="请求参数", null=True, blank=True, help_text="请求参数")
request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True, help_text="请求方式")
request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")
request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True, help_text="请求ip地址")
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True, help_text="请求浏览器")
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码")
request_os = models.CharField(max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
json_result = models.TextField(verbose_name="返回信息", null=True, blank=True, help_text="返回信息")
request_modular = models.CharField(
max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块"
)
request_path = models.CharField(
max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址"
)
request_body = models.TextField(
verbose_name="请求参数", null=True, blank=True, help_text="请求参数"
)
request_method = models.CharField(
max_length=8, verbose_name="请求方式", null=True, blank=True, help_text="请求方式"
)
request_msg = models.TextField(
verbose_name="操作说明", null=True, blank=True, help_text="操作说明"
)
request_ip = models.CharField(
max_length=32, verbose_name="请求ip地址", null=True, blank=True, help_text="请求ip地址"
)
request_browser = models.CharField(
max_length=64, verbose_name="请求浏览器", null=True, blank=True, help_text="请求浏览器"
)
response_code = models.CharField(
max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码"
)
request_os = models.CharField(
max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统"
)
json_result = models.TextField(
verbose_name="返回信息", null=True, blank=True, help_text="返回信息"
)
status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")
class Meta:
db_table = table_prefix + 'system_operation_log'
verbose_name = '操作日志'
db_table = table_prefix + "system_operation_log"
verbose_name = "操作日志"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
ordering = ("-create_datetime",)
def media_file_name(instance, filename):
h = instance.md5sum
basename, ext = os.path.splitext(filename)
return os.path.join('files', h[0:1], h[1:2], h + ext.lower())
return os.path.join("files", h[0:1], h[1:2], h + ext.lower())
class FileList(CoreModel):
name = models.CharField(max_length=50, null=True, blank=True, verbose_name="名称", help_text="名称")
name = models.CharField(
max_length=50, null=True, blank=True, verbose_name="名称", help_text="名称"
)
url = models.FileField(upload_to=media_file_name)
md5sum = models.CharField(max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5")
md5sum = models.CharField(
max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5"
)
def save(self, *args, **kwargs):
if not self.md5sum: # file is new
@ -229,27 +372,39 @@ class FileList(CoreModel):
super(FileList, self).save(*args, **kwargs)
class Meta:
db_table = table_prefix + 'system_file_list'
verbose_name = '文件管理'
db_table = table_prefix + "system_file_list"
verbose_name = "文件管理"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
ordering = ("-create_datetime",)
class Area(CoreModel):
name = models.CharField(max_length=100, verbose_name="名称", help_text="名称")
code = models.CharField(max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True)
level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)", help_text="地区层级(1省份 2城市 3区县 4乡级)")
code = models.CharField(
max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True
)
level = models.BigIntegerField(
verbose_name="地区层级(1省份 2城市 3区县 4乡级)", help_text="地区层级(1省份 2城市 3区县 4乡级)"
)
pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音")
initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")
enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用")
pcode = models.ForeignKey(to='self', verbose_name='父地区编码', to_field="code", on_delete=models.CASCADE,
db_constraint=False, null=True, blank=True, help_text="父地区编码")
pcode = models.ForeignKey(
to="self",
verbose_name="父地区编码",
to_field="code",
on_delete=models.CASCADE,
db_constraint=False,
null=True,
blank=True,
help_text="父地区编码",
)
class Meta:
db_table = table_prefix + "system_area"
verbose_name = '地区表'
verbose_name = "地区表"
verbose_name_plural = verbose_name
ordering = ('code',)
ordering = ("code",)
def __str__(self):
return f"{self.name}"
@ -263,89 +418,150 @@ class ApiWhiteList(CoreModel):
(2, "PUT"),
(3, "DELETE"),
)
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True)
method = models.IntegerField(
default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法"
)
enable_datasource = models.BooleanField(
default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True
)
class Meta:
db_table = table_prefix + "api_white_list"
verbose_name = '接口白名单'
verbose_name = "接口白名单"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
ordering = ("-create_datetime",)
class SystemConfig(CoreModel):
parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE,
db_constraint=False, null=True, blank=True, help_text="父级")
class SystemConfig(AL_Node, CoreModel):
parent = models.ForeignKey(
to="self",
verbose_name="父级",
on_delete=models.CASCADE,
db_constraint=False,
null=True,
blank=True,
help_text="父级",
)
title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")
key = models.CharField(max_length=20, verbose_name="", help_text="", db_index=True)
value = models.JSONField(max_length=100, verbose_name="", help_text="", null=True, blank=True)
key = models.CharField(
max_length=20, verbose_name="", help_text="", db_index=True
)
value = models.JSONField(
max_length=100, verbose_name="", help_text="", null=True, blank=True
)
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
FORM_ITEM_TYPE_LIST = (
(0, 'text'),
(1, 'datetime'),
(2, 'date'),
(3, 'textarea'),
(4, 'select'),
(5, 'checkbox'),
(6, 'radio'),
(7, 'img'),
(8, 'file'),
(9, 'switch'),
(10, 'number'),
(11, 'array'),
(12, 'imgs'),
(13, 'foreignkey'),
(14, 'manytomany'),
(15, 'time'),
data_options = models.JSONField(
verbose_name="数据options", help_text="数据options", null=True, blank=True
)
FORM_ITEM_TYPE_LIST = (
(0, "text"),
(1, "datetime"),
(2, "date"),
(3, "textarea"),
(4, "select"),
(5, "checkbox"),
(6, "radio"),
(7, "img"),
(8, "file"),
(9, "switch"),
(10, "number"),
(11, "array"),
(12, "imgs"),
(13, "foreignkey"),
(14, "manytomany"),
(15, "time"),
)
form_item_type = models.IntegerField(
choices=FORM_ITEM_TYPE_LIST,
verbose_name="表单类型",
help_text="表单类型",
default=0,
blank=True,
)
rule = models.JSONField(
null=True, blank=True, verbose_name="校验规则", help_text="校验规则"
)
placeholder = models.CharField(
max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息"
)
form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0,
blank=True)
rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则")
placeholder = models.CharField(max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息")
setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置")
node_order_by = ["sort", "title", "key"]
class Meta:
db_table = table_prefix + "system_config"
verbose_name = '系统配置表'
verbose_name = "系统配置表"
verbose_name_plural = verbose_name
ordering = ('sort',)
ordering = ("sort",)
unique_together = (("key", "parent_id"),)
def __str__(self):
return f"{self.title}"
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
super().save(force_insert, force_update, using, update_fields)
dispatch.refresh_system_config() # 有更新则刷新系统配置
class LoginLog(CoreModel):
LOGIN_TYPE_CHOICES = (
(1, '普通登录'),
LOGIN_TYPE_CHOICES = ((1, "普通登录"),)
username = models.CharField(
max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名"
)
ip = models.CharField(
max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip"
)
agent = models.TextField(
verbose_name="agent信息", null=True, blank=True, help_text="agent信息"
)
browser = models.CharField(
max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名"
)
os = models.CharField(
max_length=200, verbose_name="操作系统", null=True, blank=True, help_text="操作系统"
)
continent = models.CharField(
max_length=50, verbose_name="", null=True, blank=True, help_text=""
)
country = models.CharField(
max_length=50, verbose_name="国家", null=True, blank=True, help_text="国家"
)
province = models.CharField(
max_length=50, verbose_name="省份", null=True, blank=True, help_text="省份"
)
city = models.CharField(
max_length=50, verbose_name="城市", null=True, blank=True, help_text="城市"
)
district = models.CharField(
max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区"
)
isp = models.CharField(
max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商"
)
area_code = models.CharField(
max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码"
)
country_english = models.CharField(
max_length=50, verbose_name="英文全称", null=True, blank=True, help_text="英文全称"
)
country_code = models.CharField(
max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称"
)
longitude = models.CharField(
max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度"
)
latitude = models.CharField(
max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度"
)
login_type = models.IntegerField(
default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型"
)
username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")
ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip")
agent = models.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息")
browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名")
os = models.CharField(max_length=200, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
continent = models.CharField(max_length=50, verbose_name="", null=True, blank=True, help_text="")
country = models.CharField(max_length=50, verbose_name="国家", null=True, blank=True, help_text="国家")
province = models.CharField(max_length=50, verbose_name="省份", null=True, blank=True, help_text="省份")
city = models.CharField(max_length=50, verbose_name="城市", null=True, blank=True, help_text="城市")
district = models.CharField(max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区")
isp = models.CharField(max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商")
area_code = models.CharField(max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码")
country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True, help_text="英文全称")
country_code = models.CharField(max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称")
longitude = models.CharField(max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度")
latitude = models.CharField(max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度")
login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型")
class Meta:
db_table = table_prefix + 'system_login_log'
verbose_name = '登录日志'
db_table = table_prefix + "system_login_log"
verbose_name = "登录日志"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
ordering = ("-create_datetime",)

View File

@ -31,6 +31,7 @@ class DictionaryInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: Dictionary):
@ -43,29 +44,40 @@ class DictionaryInitSerializer(CustomModelSerializer):
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
children = self.initial_data.get("children")
# 菜单表
if children:
for data in children:
data['parent'] = instance.id
filter_data = {
"value": data['value'],
"parent": data['parent']
}
data["parent"] = instance.id
filter_data = {"value": data["value"], "parent": data["parent"]}
instance_obj = Dictionary.objects.filter(**filter_data).first()
serializer = DictionaryInitSerializer(instance_obj, data=data, request=self.request)
serializer = DictionaryInitSerializer(
instance_obj, data=data, request=self.request
)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Dictionary
fields = ['label', 'value', 'parent', 'type', 'color', 'is_value', 'status', 'sort', 'remark', 'creator',
'dept_belong_id', 'children']
fields = [
"label",
"value",
"parent",
"type",
"color",
"is_value",
"status",
"sort",
"remark",
"creator",
"dept_belong_id",
"children",
]
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
"creator": {"write_only": True},
"dept_belong_id": {"write_only": True},
}
@ -76,7 +88,7 @@ class DictionaryCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Dictionary
fields = '__all__'
fields = "__all__"
class DictionaryViewSet(CustomModelViewSet):
@ -88,30 +100,46 @@ class DictionaryViewSet(CustomModelViewSet):
retrieve:单例
destroy:删除
"""
queryset = Dictionary.objects.all()
serializer_class = DictionarySerializer
extra_filter_backends = []
search_fields = ['label']
search_fields = ["label"]
def get_queryset(self):
parent_id = self.request.query_params.get("parent", None)
if parent_id:
return self.queryset.get(id=parent_id).get_children()
return super().get_queryset()
class InitDictionaryViewSet(APIView):
"""
获取初始化配置
"""
authentication_classes = []
permission_classes = []
queryset = Dictionary.objects.all()
def get(self, request):
dictionary_key = self.request.query_params.get('dictionary_key')
dictionary_key = self.request.query_params.get("dictionary_key")
if dictionary_key:
if dictionary_key == 'all':
if dictionary_key == "all":
data = [ele for ele in dispatch.get_dictionary_config().values()]
if not data:
dispatch.refresh_dictionary()
data = [ele for ele in dispatch.get_dictionary_config().values()]
else:
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
'color')
# data = self.queryset.filter(
# parent__value=dictionary_key, status=True
# ).values("label", "value", "type", "color")
data = (
Dictionary.objects.get(value=dictionary_key)
.get_children()
.filter(status=True)
.values("label", "value", "type", "color")
)
print(data)
return SuccessResponse(data=data, msg="获取成功")
return SuccessResponse(data=[], msg="获取成功")

View File

@ -20,10 +20,19 @@ class MenuSerializer(CustomModelSerializer):
"""
菜单表的简单序列化器
"""
parent = serializers.SerializerMethodField(read_only=True)
menuPermission = serializers.SerializerMethodField(read_only=True)
def get_parent(self, instance):
return instance.get_parent().id if instance.get_parent() else None
def get_menuPermission(self, instance):
queryset = MenuButton.objects.filter(menu=instance.id).order_by('-name').values_list('name', flat=True)
queryset = (
MenuButton.objects.filter(menu=instance.id)
.order_by("-name")
.values_list("name", flat=True)
)
if queryset:
return queryset
else:
@ -39,6 +48,7 @@ class MenuCreateSerializer(CustomModelSerializer):
"""
菜单表的创建序列化器
"""
name = serializers.CharField(required=False)
class Meta:
@ -51,6 +61,7 @@ class MenuInitSerializer(CustomModelSerializer):
"""
递归深度获取数信息(用于生成初始化json文件)
"""
name = serializers.CharField(required=False)
children = serializers.SerializerMethodField()
menu_button = serializers.SerializerMethodField()
@ -65,70 +76,97 @@ class MenuInitSerializer(CustomModelSerializer):
def get_menu_button(self, obj: Menu):
data = []
instance = MenuButton.objects.filter(menu_id=obj.id).order_by('method')
instance = MenuButton.objects.filter(menu_id=obj.id).order_by("method")
if instance:
data = list(instance.values('name', 'value', 'api', 'method'))
data = list(instance.values("name", "value", "api", "method"))
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
menu_button = self.initial_data.get('menu_button')
children = self.initial_data.get("children")
menu_button = self.initial_data.get("menu_button")
# 菜单表
if children:
for menu_data in children:
menu_data['parent'] = instance.id
menu_data["parent"] = instance.id
filter_data = {
"name": menu_data['name'],
"web_path": menu_data['web_path'],
"component": menu_data['component'],
"component_name": menu_data['component_name'],
"name": menu_data["name"],
"web_path": menu_data["web_path"],
"component": menu_data["component"],
"component_name": menu_data["component_name"],
}
instance_obj = Menu.objects.filter(**filter_data).first()
serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
serializer = MenuInitSerializer(
instance_obj, data=menu_data, request=self.request
)
serializer.is_valid(raise_exception=True)
serializer.save()
# 菜单按钮
if menu_button:
for menu_button_data in menu_button:
menu_button_data['menu'] = instance.id
menu_button_data["menu"] = instance.id
filter_data = {
"menu": menu_button_data['menu'],
"value": menu_button_data['value']
"menu": menu_button_data["menu"],
"value": menu_button_data["value"],
}
instance_obj = MenuButton.objects.filter(**filter_data).first()
serializer = MenuButtonSerializer(instance_obj, data=menu_button_data, request=self.request)
serializer = MenuButtonSerializer(
instance_obj, data=menu_button_data, request=self.request
)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Menu
fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
fields = [
"name",
"icon",
"sort",
"is_link",
"is_catalog",
"web_path",
"component",
"component_name",
"status",
"cache",
"visible",
"parent",
"children",
"menu_button",
"creator",
"dept_belong_id",
]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
"creator": {"write_only": True},
"dept_belong_id": {"write_only": True},
}
read_only_fields = ['id', 'children']
read_only_fields = ["id", "children"]
class WebRouterSerializer(CustomModelSerializer):
"""
前端菜单路由的简单序列化器
"""
path = serializers.CharField(source="web_path")
title = serializers.CharField(source="name")
parent = serializers.SerializerMethodField(read_only=True)
menuPermission = serializers.SerializerMethodField(read_only=True)
def get_parent(self, instance):
return instance.get_parent().id if instance.get_parent() else None
def get_menuPermission(self, instance):
# 判断是否是超级管理员
if self.request.user.is_superuser:
return MenuButton.objects.values_list('value', flat=True)
return MenuButton.objects.values_list("value", flat=True)
else:
# 根据当前角色获取权限按钮id集合
permissionIds = self.request.user.role.values_list('permission', flat=True)
queryset = MenuButton.objects.filter(id__in=permissionIds, menu=instance.id).values_list('value', flat=True)
permissionIds = self.request.user.role.values_list("permission", flat=True)
queryset = MenuButton.objects.filter(
id__in=permissionIds, menu=instance.id
).values_list("value", flat=True)
if queryset:
return queryset
else:
@ -149,21 +187,29 @@ class MenuViewSet(CustomModelViewSet):
retrieve:单例
destroy:删除
"""
queryset = Menu.objects.all()
serializer_class = MenuSerializer
create_serializer_class = MenuCreateSerializer
update_serializer_class = MenuCreateSerializer
search_fields = ['name', 'status']
filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog']
search_fields = ["name", "status"]
filter_fields = [
"name",
"status",
"is_link",
"visible",
"cache",
"is_catalog",
]
extra_filter_backends = []
@action(methods=['GET'], detail=True, permission_classes=[])
@action(methods=["GET"], detail=True, permission_classes=[])
def web_router(self, request):
"""用于前端获取当前角色的路由"""
user = request.user
queryset = self.queryset.filter(status=1)
if not user.is_superuser:
menuIds = user.role.values_list('menu__id', flat=True)
menuIds = user.role.values_list("menu__id", flat=True)
queryset = Menu.objects.filter(id__in=menuIds, status=1)
serializer = WebRouterSerializer(queryset, many=True, request=request)
data = serializer.data

View File

@ -7,12 +7,14 @@ from rest_framework import request
from application import settings
from dvadmin.system.models import Users
from treebeard.mp_tree import MP_Node
class CoreInitialize:
"""
使用方法继承此类重写 run方法 run 中调用 save 进行数据初始化
"""
creator_id = None
reset = False
request = request
@ -25,13 +27,16 @@ class CoreInitialize:
"""
self.reset = reset or self.reset
self.creator_id = creator_id or self.creator_id
self.app = app or ''
self.request.user = Users.objects.order_by('create_datetime').first()
self.app = app or ""
self.request.user = Users.objects.order_by("create_datetime").first()
def init_base(self, Serializer, unique_fields=None):
model = Serializer.Meta.model
path_file = os.path.join(apps.get_app_config(self.app.split('.')[-1]).path, 'fixtures',
f'init_{Serializer.Meta.model._meta.model_name}.json')
path_file = os.path.join(
apps.get_app_config(self.app.split(".")[-1]).path,
"fixtures",
f"init_{Serializer.Meta.model._meta.model_name}.json",
)
if not os.path.isfile(path_file):
return
with open(path_file) as f:
@ -44,7 +49,7 @@ class CoreInitialize:
filter_data[field] = data[field]
else:
for key, value in data.items():
if isinstance(value, list) or value == None or value == '':
if isinstance(value, list) or value == None or value == "":
continue
filter_data[key] = value
instance = model.objects.filter(**filter_data).first()
@ -62,6 +67,9 @@ class CoreInitialize:
settings.INITIALIZE_RESET_LIST.append(obj)
except Exception:
pass
if MP_Node in obj.__mro__:
obj.load_bulk(data, None, True)
else:
for ele in data:
m2m_dict = {}
new_data = {}
@ -71,17 +79,21 @@ class CoreInitialize:
m2m_dict[key] = value
else:
new_data[key] = value
object, _ = obj.objects.get_or_create(id=ele.get("id"), defaults=new_data)
object, _ = obj.objects.get_or_create(
id=ele.get("id"), defaults=new_data
)
for key, m2m in m2m_dict.items():
m2m = list(set(m2m))
if m2m and len(m2m) > 0 and m2m[0]:
exec(f"""
exec(
f"""
if object.{key}:
values_list = object.{key}.all().values_list('id', flat=True)
values_list = list(set(list(values_list) + {m2m}))
object.{key}.set(values_list)
""")
"""
)
print(f"初始化完成[{obj._meta.label} => {name}]")
def run(self):
raise NotImplementedError('.run() must be overridden')
raise NotImplementedError(".run() must be overridden")

View File

@ -23,6 +23,10 @@ class CustomModelSerializer(DynamicFieldsMixin, ModelSerializer):
(1)self.request能获取到rest_framework.request.Request对象
"""
# 放空treebeard.mp_tree.MP_Node的继承字段
path = serializers.CharField(required=False)
depth = serializers.IntegerField(required=False)
# 修改人的审计字段名称, 默认modifier, 继承使用时可自定义覆盖
modifier_field_id = "modifier"
modifier_name = serializers.SerializerMethodField(read_only=True)

View File

@ -14,12 +14,19 @@ from rest_framework.decorators import action
from rest_framework.viewsets import ModelViewSet
from dvadmin.utils.filters import DataLevelPermissionsFilter
from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSerializerMixin
from dvadmin.utils.import_export_mixin import (
ExportSerializerMixin,
ImportSerializerMixin,
)
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse
from dvadmin.utils.permission import CustomPermission
from django_restql.mixins import QueryArgumentsMixin
from treebeard.models import Node
class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixin,QueryArgumentsMixin):
class CustomModelViewSet(
ModelViewSet, ImportSerializerMixin, ExportSerializerMixin, QueryArgumentsMixin
):
"""
自定义的ModelViewSet:
统一标准的返回格式;新增,查询,修改可使用不同序列化器
@ -29,11 +36,12 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
(4)import_field_dict={} 导入时的字段字典 {model值: model的label}
(5)export_field_label = [] 导出时的字段
"""
values_queryset = None
ordering_fields = '__all__'
ordering_fields = "__all__"
create_serializer_class = None
update_serializer_class = None
filter_fields = '__all__'
filter_fields = "__all__"
search_fields = ()
extra_filter_backends = [DataLevelPermissionsFilter]
permission_classes = [CustomPermission]
@ -41,12 +49,14 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
export_field_label = []
def filter_queryset(self, queryset):
for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])):
for backend in set(
set(self.filter_backends) | set(self.extra_filter_backends or [])
):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
def get_queryset(self):
if getattr(self, 'values_queryset', None):
if getattr(self, "values_queryset", None):
return self.values_queryset
return super().get_queryset()
@ -60,6 +70,15 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data, request=request)
serializer.is_valid(raise_exception=True)
if Node in self.queryset.model.__mro__:
parent_id = request.data.get("parent")
data = serializer.validated_data
if parent_id is None:
self.queryset.model.add_root(**data)
else:
parent = self.queryset.model.objects.filter(pk=parent_id).first()
parent.add_child(**data)
return DetailResponse(data=data, msg="新增成功")
self.perform_create(serializer)
return DetailResponse(data=serializer.data, msg="新增成功")
@ -78,13 +97,15 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
return DetailResponse(data=serializer.data, msg="获取成功")
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
partial = kwargs.pop("partial", False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, request=request, partial=partial)
serializer = self.get_serializer(
instance, data=request.data, request=request, partial=partial
)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
if getattr(instance, "_prefetched_objects_cache", None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
@ -95,17 +116,20 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
self.perform_destroy(instance)
return DetailResponse(data=[], msg="删除成功")
keys = openapi.Schema(
description="主键列表", type=openapi.TYPE_ARRAY, items=openapi.TYPE_STRING
)
keys = openapi.Schema(description='主键列表',type=openapi.TYPE_ARRAY,items=openapi.TYPE_STRING)
@swagger_auto_schema(request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['keys'],
properties={'keys': keys}
), operation_summary='批量删除')
@action(methods=['delete'],detail=False)
@swagger_auto_schema(
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT, required=["keys"], properties={"keys": keys}
),
operation_summary="批量删除",
)
@action(methods=["delete"], detail=False)
def multiple_delete(self, request, *args, **kwargs):
request_data = request.data
keys = request_data.get('keys',None)
keys = request_data.get("keys", None)
if keys:
self.get_queryset().filter(id__in=keys).delete()
return SuccessResponse(data=[], msg="删除成功")

View File

@ -41,3 +41,4 @@ urllib3==1.26.6
user-agents==2.2.0
whitenoise==5.3.0
openpyxl==3.0.9
django-treebeard>=4.5.1

View File

@ -379,7 +379,7 @@ export const crudOptions = (vm) => {
search: {
disabled: false
},
width: 50,
width: 60,
type: 'radio',
dict: {
data: vm.dictionary('button_whether_bool')

File diff suppressed because it is too large Load Diff