Merge branch 'temp' into treebeard
commit
d6f8c707a1
|
@ -10,7 +10,7 @@ def is_tenants_mode():
|
||||||
判断是否为租户模式
|
判断是否为租户模式
|
||||||
:return:
|
: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():
|
def _get_all_dictionary():
|
||||||
from dvadmin.system.models import Dictionary
|
from dvadmin.system.models import Dictionary
|
||||||
|
|
||||||
queryset = Dictionary.objects.filter(status=True, is_value=False)
|
queryset = Dictionary.objects.filter(status=True, is_value=False)
|
||||||
data = []
|
data = []
|
||||||
for instance in queryset:
|
for instance in queryset:
|
||||||
data.append({
|
data.append(
|
||||||
"id": instance.id,
|
{
|
||||||
"value": instance.value,
|
"id": instance.id,
|
||||||
"children": list(Dictionary.objects.filter(parent=instance.id).filter(status=1).
|
"value": instance.value,
|
||||||
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}
|
return {ele.get("value"): ele for ele in data}
|
||||||
|
|
||||||
|
|
||||||
def _get_all_system_config():
|
def _get_all_system_config():
|
||||||
data = {}
|
data = {}
|
||||||
from dvadmin.system.models import SystemConfig
|
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:
|
for system_config in system_config_obj:
|
||||||
value = system_config.get('value') or ''
|
value = system_config.get("value") or ""
|
||||||
if value and system_config.get('form_item_type') == 7:
|
if value and system_config.get("form_item_type") == 7:
|
||||||
value = value[0].get('url')
|
value = value[0].get("url")
|
||||||
data[f"{system_config.get('parent__key')}.{system_config.get('key')}"] = value
|
data[f"{system_config.get('parent__key')}.{system_config.get('key')}"] = value
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -51,9 +61,12 @@ def init_dictionary():
|
||||||
try:
|
try:
|
||||||
if is_tenants_mode():
|
if is_tenants_mode():
|
||||||
from django_tenants.utils import tenant_context, get_tenant_model
|
from django_tenants.utils import tenant_context, get_tenant_model
|
||||||
|
|
||||||
for tenant in get_tenant_model().objects.filter():
|
for tenant in get_tenant_model().objects.filter():
|
||||||
with tenant_context(tenant):
|
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:
|
else:
|
||||||
settings.DICTIONARY_CONFIG = _get_all_dictionary()
|
settings.DICTIONARY_CONFIG = _get_all_dictionary()
|
||||||
print("初始化字典配置完成")
|
print("初始化字典配置完成")
|
||||||
|
@ -72,9 +85,12 @@ def init_system_config():
|
||||||
|
|
||||||
if is_tenants_mode():
|
if is_tenants_mode():
|
||||||
from django_tenants.utils import tenant_context, get_tenant_model
|
from django_tenants.utils import tenant_context, get_tenant_model
|
||||||
|
|
||||||
for tenant in get_tenant_model().objects.filter():
|
for tenant in get_tenant_model().objects.filter():
|
||||||
with tenant_context(tenant):
|
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:
|
else:
|
||||||
settings.SYSTEM_CONFIG = _get_all_system_config()
|
settings.SYSTEM_CONFIG = _get_all_system_config()
|
||||||
print("初始化系统配置完成")
|
print("初始化系统配置完成")
|
||||||
|
@ -90,9 +106,12 @@ def refresh_dictionary():
|
||||||
"""
|
"""
|
||||||
if is_tenants_mode():
|
if is_tenants_mode():
|
||||||
from django_tenants.utils import tenant_context, get_tenant_model
|
from django_tenants.utils import tenant_context, get_tenant_model
|
||||||
|
|
||||||
for tenant in get_tenant_model().objects.filter():
|
for tenant in get_tenant_model().objects.filter():
|
||||||
with tenant_context(tenant):
|
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:
|
else:
|
||||||
settings.DICTIONARY_CONFIG = _get_all_dictionary()
|
settings.DICTIONARY_CONFIG = _get_all_dictionary()
|
||||||
|
|
||||||
|
@ -104,9 +123,12 @@ def refresh_system_config():
|
||||||
"""
|
"""
|
||||||
if is_tenants_mode():
|
if is_tenants_mode():
|
||||||
from django_tenants.utils import tenant_context, get_tenant_model
|
from django_tenants.utils import tenant_context, get_tenant_model
|
||||||
|
|
||||||
for tenant in get_tenant_model().objects.filter():
|
for tenant in get_tenant_model().objects.filter():
|
||||||
with tenant_context(tenant):
|
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:
|
else:
|
||||||
settings.SYSTEM_CONFIG = _get_all_system_config()
|
settings.SYSTEM_CONFIG = _get_all_system_config()
|
||||||
|
|
||||||
|
@ -121,7 +143,9 @@ def get_dictionary_config(schema_name=None):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if is_tenants_mode():
|
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:
|
else:
|
||||||
dictionary_config = settings.DICTIONARY_CONFIG
|
dictionary_config = settings.DICTIONARY_CONFIG
|
||||||
return dictionary_config or {}
|
return dictionary_config or {}
|
||||||
|
@ -165,7 +189,9 @@ def get_system_config(schema_name=None):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if is_tenants_mode():
|
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:
|
else:
|
||||||
dictionary_config = settings.SYSTEM_CONFIG
|
dictionary_config = settings.SYSTEM_CONFIG
|
||||||
return dictionary_config or {}
|
return dictionary_config or {}
|
||||||
|
|
|
@ -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()
|
|
@ -1,6 +1,9 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
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.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -14,62 +17,107 @@ STATUS_CHOICES = (
|
||||||
|
|
||||||
|
|
||||||
class Users(AbstractUser, CoreModel):
|
class Users(AbstractUser, CoreModel):
|
||||||
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号', help_text="用户账号")
|
username = models.CharField(
|
||||||
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
|
max_length=150,
|
||||||
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
|
unique=True,
|
||||||
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
|
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="姓名")
|
name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")
|
||||||
GENDER_CHOICES = (
|
GENDER_CHOICES = (
|
||||||
(0, "未知"),
|
(0, "未知"),
|
||||||
(1, "男"),
|
(1, "男"),
|
||||||
(2, "女"),
|
(2, "女"),
|
||||||
)
|
)
|
||||||
gender = models.IntegerField(choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True,
|
gender = models.IntegerField(
|
||||||
help_text="性别")
|
choices=GENDER_CHOICES,
|
||||||
|
default=0,
|
||||||
|
verbose_name="性别",
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
help_text="性别",
|
||||||
|
)
|
||||||
USER_TYPE = (
|
USER_TYPE = (
|
||||||
(0, "后台用户"),
|
(0, "后台用户"),
|
||||||
(1, "前台用户"),
|
(1, "前台用户"),
|
||||||
)
|
)
|
||||||
user_type = models.IntegerField(choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True,
|
user_type = models.IntegerField(
|
||||||
help_text="用户类型")
|
choices=USER_TYPE,
|
||||||
post = models.ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False, help_text="关联岗位")
|
default=0,
|
||||||
role = models.ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False, help_text="关联角色")
|
verbose_name="用户类型",
|
||||||
dept = models.ForeignKey(to='Dept', verbose_name='所属部门', on_delete=models.PROTECT, db_constraint=False, null=True,
|
null=True,
|
||||||
blank=True, help_text="关联部门")
|
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):
|
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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_users"
|
db_table = table_prefix + "system_users"
|
||||||
verbose_name = '用户表'
|
verbose_name = "用户表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-create_datetime',)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
||||||
class Post(CoreModel):
|
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="岗位编码")
|
code = models.CharField(max_length=32, verbose_name="岗位编码", help_text="岗位编码")
|
||||||
sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")
|
sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")
|
||||||
STATUS_CHOICES = (
|
STATUS_CHOICES = (
|
||||||
(0, "离职"),
|
(0, "离职"),
|
||||||
(1, "在职"),
|
(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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_post"
|
db_table = table_prefix + "system_post"
|
||||||
verbose_name = '岗位表'
|
verbose_name = "岗位表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
ordering = ("sort",)
|
||||||
|
|
||||||
|
|
||||||
class Role(CoreModel):
|
class Role(CoreModel):
|
||||||
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
|
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="角色顺序")
|
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
|
||||||
status = models.BooleanField(default=True, 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 = (
|
DATASCOPE_CHOICES = (
|
||||||
(0, "仅本人数据权限"),
|
(0, "仅本人数据权限"),
|
||||||
(1, "本部门及以下数据权限"),
|
(1, "本部门及以下数据权限"),
|
||||||
|
@ -77,67 +125,119 @@ class Role(CoreModel):
|
||||||
(3, "全部数据权限"),
|
(3, "全部数据权限"),
|
||||||
(4, "自定数据权限"),
|
(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)
|
remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
|
||||||
dept = models.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False, help_text="数据权限-关联部门")
|
dept = models.ManyToManyField(
|
||||||
menu = models.ManyToManyField(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text="关联菜单")
|
to="Dept", verbose_name="数据权限-关联部门", db_constraint=False, help_text="数据权限-关联部门"
|
||||||
permission = models.ManyToManyField(to='MenuButton', 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:
|
class Meta:
|
||||||
db_table = table_prefix + 'system_role'
|
db_table = table_prefix + "system_role"
|
||||||
verbose_name = '角色表'
|
verbose_name = "角色表"
|
||||||
verbose_name_plural = 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="部门名称")
|
name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称")
|
||||||
sort = models.IntegerField(default=1, 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="负责人")
|
owner = models.CharField(
|
||||||
phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")
|
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,
|
phone = models.CharField(
|
||||||
help_text="部门状态")
|
max_length=32, 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="上级部门")
|
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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_dept"
|
db_table = table_prefix + "system_dept"
|
||||||
verbose_name = '部门表'
|
verbose_name = "部门表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
ordering = ("sort",)
|
||||||
|
|
||||||
|
|
||||||
class Menu(CoreModel):
|
class Menu(MP_Node, CoreModel):
|
||||||
parent = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name="上级菜单", null=True, blank=True,
|
icon = models.CharField(
|
||||||
db_constraint=False, help_text="上级菜单")
|
max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标"
|
||||||
icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标")
|
)
|
||||||
name = models.CharField(max_length=64, verbose_name="菜单名称", 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 = (
|
ISLINK_CHOICES = (
|
||||||
(0, "否"),
|
(0, "否"),
|
||||||
(1, "是"),
|
(1, "是"),
|
||||||
)
|
)
|
||||||
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
|
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
|
||||||
is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")
|
is_catalog = models.BooleanField(
|
||||||
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
|
default=False, verbose_name="是否目录", 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="组件名称")
|
web_path = models.CharField(
|
||||||
status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")
|
max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址"
|
||||||
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
|
)
|
||||||
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示", 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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_menu"
|
db_table = table_prefix + "system_menu"
|
||||||
verbose_name = '菜单表'
|
verbose_name = "菜单表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
ordering = ("sort",)
|
||||||
|
|
||||||
|
|
||||||
class MenuButton(CoreModel):
|
class MenuButton(CoreModel):
|
||||||
menu = models.ForeignKey(to="Menu", db_constraint=False, related_name="menuPermission", on_delete=models.CASCADE,
|
menu = models.ForeignKey(
|
||||||
verbose_name="关联菜单", help_text='关联菜单')
|
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="名称")
|
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
|
||||||
value = 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="接口地址")
|
api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")
|
||||||
|
@ -147,78 +247,121 @@ class MenuButton(CoreModel):
|
||||||
(2, "PUT"),
|
(2, "PUT"),
|
||||||
(3, "DELETE"),
|
(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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_menu_button"
|
db_table = table_prefix + "system_menu_button"
|
||||||
verbose_name = '菜单权限表'
|
verbose_name = "菜单权限表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-name',)
|
ordering = ("-name",)
|
||||||
|
|
||||||
|
|
||||||
class Dictionary(CoreModel):
|
class Dictionary(MP_Node, CoreModel):
|
||||||
TYPE_LIST = (
|
TYPE_LIST = (
|
||||||
(0, 'text'),
|
(0, "text"),
|
||||||
(1, 'number'),
|
(1, "number"),
|
||||||
(2, 'date'),
|
(2, "date"),
|
||||||
(3, 'datetime'),
|
(3, "datetime"),
|
||||||
(4, 'time'),
|
(4, "time"),
|
||||||
(5, 'files'),
|
(5, "files"),
|
||||||
(6, 'boolean'),
|
(6, "boolean"),
|
||||||
(7, 'images'),
|
(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="状态")
|
status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")
|
||||||
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
|
sort = models.IntegerField(
|
||||||
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
|
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:
|
class Meta:
|
||||||
db_table = table_prefix + 'system_dictionary'
|
db_table = table_prefix + "system_dictionary"
|
||||||
verbose_name = "字典表"
|
verbose_name = "字典表"
|
||||||
verbose_name_plural = 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)
|
super().save(force_insert, force_update, using, update_fields)
|
||||||
dispatch.refresh_dictionary() # 有更新则刷新字典配置
|
dispatch.refresh_dictionary() # 有更新则刷新字典配置
|
||||||
|
|
||||||
|
|
||||||
class OperationLog(CoreModel):
|
class OperationLog(CoreModel):
|
||||||
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
|
request_modular = models.CharField(
|
||||||
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址")
|
max_length=64, 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_path = models.CharField(
|
||||||
request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")
|
max_length=400, 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="请求浏览器")
|
request_body = models.TextField(
|
||||||
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码")
|
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_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="响应状态")
|
status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + 'system_operation_log'
|
db_table = table_prefix + "system_operation_log"
|
||||||
verbose_name = '操作日志'
|
verbose_name = "操作日志"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-create_datetime',)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
||||||
def media_file_name(instance, filename):
|
def media_file_name(instance, filename):
|
||||||
h = instance.md5sum
|
h = instance.md5sum
|
||||||
basename, ext = os.path.splitext(filename)
|
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):
|
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)
|
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):
|
def save(self, *args, **kwargs):
|
||||||
if not self.md5sum: # file is new
|
if not self.md5sum: # file is new
|
||||||
|
@ -229,27 +372,39 @@ class FileList(CoreModel):
|
||||||
super(FileList, self).save(*args, **kwargs)
|
super(FileList, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + 'system_file_list'
|
db_table = table_prefix + "system_file_list"
|
||||||
verbose_name = '文件管理'
|
verbose_name = "文件管理"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-create_datetime',)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
||||||
class Area(CoreModel):
|
class Area(CoreModel):
|
||||||
name = models.CharField(max_length=100, verbose_name="名称", help_text="名称")
|
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)
|
code = models.CharField(
|
||||||
level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)", help_text="地区层级(1省份 2城市 3区县 4乡级)")
|
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="拼音")
|
pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音")
|
||||||
initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")
|
initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")
|
||||||
enable = models.BooleanField(default=True, 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,
|
pcode = models.ForeignKey(
|
||||||
db_constraint=False, null=True, blank=True, help_text="父地区编码")
|
to="self",
|
||||||
|
verbose_name="父地区编码",
|
||||||
|
to_field="code",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
db_constraint=False,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
help_text="父地区编码",
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "system_area"
|
db_table = table_prefix + "system_area"
|
||||||
verbose_name = '地区表'
|
verbose_name = "地区表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('code',)
|
ordering = ("code",)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name}"
|
return f"{self.name}"
|
||||||
|
@ -263,89 +418,150 @@ class ApiWhiteList(CoreModel):
|
||||||
(2, "PUT"),
|
(2, "PUT"),
|
||||||
(3, "DELETE"),
|
(3, "DELETE"),
|
||||||
)
|
)
|
||||||
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
|
method = models.IntegerField(
|
||||||
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True)
|
default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法"
|
||||||
|
)
|
||||||
|
enable_datasource = models.BooleanField(
|
||||||
|
default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "api_white_list"
|
db_table = table_prefix + "api_white_list"
|
||||||
verbose_name = '接口白名单'
|
verbose_name = "接口白名单"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-create_datetime',)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
||||||
class SystemConfig(CoreModel):
|
class SystemConfig(AL_Node, CoreModel):
|
||||||
parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE,
|
parent = models.ForeignKey(
|
||||||
db_constraint=False, null=True, blank=True, help_text="父级")
|
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="标题")
|
title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")
|
||||||
key = models.CharField(max_length=20, verbose_name="键", help_text="键", db_index=True)
|
key = models.CharField(
|
||||||
value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True)
|
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)
|
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
|
||||||
status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")
|
status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")
|
||||||
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
data_options = models.JSONField(
|
||||||
FORM_ITEM_TYPE_LIST = (
|
verbose_name="数据options", help_text="数据options", null=True, blank=True
|
||||||
(0, 'text'),
|
)
|
||||||
(1, 'datetime'),
|
FORM_ITEM_TYPE_LIST = (
|
||||||
(2, 'date'),
|
(0, "text"),
|
||||||
(3, 'textarea'),
|
(1, "datetime"),
|
||||||
(4, 'select'),
|
(2, "date"),
|
||||||
(5, 'checkbox'),
|
(3, "textarea"),
|
||||||
(6, 'radio'),
|
(4, "select"),
|
||||||
(7, 'img'),
|
(5, "checkbox"),
|
||||||
(8, 'file'),
|
(6, "radio"),
|
||||||
(9, 'switch'),
|
(7, "img"),
|
||||||
(10, 'number'),
|
(8, "file"),
|
||||||
(11, 'array'),
|
(9, "switch"),
|
||||||
(12, 'imgs'),
|
(10, "number"),
|
||||||
(13, 'foreignkey'),
|
(11, "array"),
|
||||||
(14, 'manytomany'),
|
(12, "imgs"),
|
||||||
(15, 'time'),
|
(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="配置")
|
setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置")
|
||||||
|
|
||||||
|
node_order_by = ["sort", "title", "key"]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "system_config"
|
db_table = table_prefix + "system_config"
|
||||||
verbose_name = '系统配置表'
|
verbose_name = "系统配置表"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
ordering = ("sort",)
|
||||||
unique_together = (("key", "parent_id"),)
|
unique_together = (("key", "parent_id"),)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title}"
|
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)
|
super().save(force_insert, force_update, using, update_fields)
|
||||||
dispatch.refresh_system_config() # 有更新则刷新系统配置
|
dispatch.refresh_system_config() # 有更新则刷新系统配置
|
||||||
|
|
||||||
|
|
||||||
class LoginLog(CoreModel):
|
class LoginLog(CoreModel):
|
||||||
LOGIN_TYPE_CHOICES = (
|
LOGIN_TYPE_CHOICES = ((1, "普通登录"),)
|
||||||
(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:
|
class Meta:
|
||||||
db_table = table_prefix + 'system_login_log'
|
db_table = table_prefix + "system_login_log"
|
||||||
verbose_name = '登录日志'
|
verbose_name = "登录日志"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('-create_datetime',)
|
ordering = ("-create_datetime",)
|
||||||
|
|
|
@ -31,6 +31,7 @@ class DictionaryInitSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
初始化获取数信息(用于生成初始化json文件)
|
初始化获取数信息(用于生成初始化json文件)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
children = serializers.SerializerMethodField()
|
children = serializers.SerializerMethodField()
|
||||||
|
|
||||||
def get_children(self, obj: Dictionary):
|
def get_children(self, obj: Dictionary):
|
||||||
|
@ -43,29 +44,40 @@ class DictionaryInitSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
instance = super().save(**kwargs)
|
instance = super().save(**kwargs)
|
||||||
children = self.initial_data.get('children')
|
children = self.initial_data.get("children")
|
||||||
# 菜单表
|
# 菜单表
|
||||||
if children:
|
if children:
|
||||||
for data in children:
|
for data in children:
|
||||||
data['parent'] = instance.id
|
data["parent"] = instance.id
|
||||||
filter_data = {
|
filter_data = {"value": data["value"], "parent": data["parent"]}
|
||||||
"value": data['value'],
|
|
||||||
"parent": data['parent']
|
|
||||||
}
|
|
||||||
instance_obj = Dictionary.objects.filter(**filter_data).first()
|
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.is_valid(raise_exception=True)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Dictionary
|
model = Dictionary
|
||||||
fields = ['label', 'value', 'parent', 'type', 'color', 'is_value', 'status', 'sort', 'remark', 'creator',
|
fields = [
|
||||||
'dept_belong_id', 'children']
|
"label",
|
||||||
|
"value",
|
||||||
|
"parent",
|
||||||
|
"type",
|
||||||
|
"color",
|
||||||
|
"is_value",
|
||||||
|
"status",
|
||||||
|
"sort",
|
||||||
|
"remark",
|
||||||
|
"creator",
|
||||||
|
"dept_belong_id",
|
||||||
|
"children",
|
||||||
|
]
|
||||||
read_only_fields = ["id"]
|
read_only_fields = ["id"]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'creator': {'write_only': True},
|
"creator": {"write_only": True},
|
||||||
'dept_belong_id': {'write_only': True}
|
"dept_belong_id": {"write_only": True},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,7 +88,7 @@ class DictionaryCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Dictionary
|
model = Dictionary
|
||||||
fields = '__all__'
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class DictionaryViewSet(CustomModelViewSet):
|
class DictionaryViewSet(CustomModelViewSet):
|
||||||
|
@ -88,30 +100,46 @@ class DictionaryViewSet(CustomModelViewSet):
|
||||||
retrieve:单例
|
retrieve:单例
|
||||||
destroy:删除
|
destroy:删除
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = Dictionary.objects.all()
|
queryset = Dictionary.objects.all()
|
||||||
serializer_class = DictionarySerializer
|
serializer_class = DictionarySerializer
|
||||||
extra_filter_backends = []
|
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):
|
class InitDictionaryViewSet(APIView):
|
||||||
"""
|
"""
|
||||||
获取初始化配置
|
获取初始化配置
|
||||||
"""
|
"""
|
||||||
|
|
||||||
authentication_classes = []
|
authentication_classes = []
|
||||||
permission_classes = []
|
permission_classes = []
|
||||||
queryset = Dictionary.objects.all()
|
queryset = Dictionary.objects.all()
|
||||||
|
|
||||||
def get(self, request):
|
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:
|
||||||
if dictionary_key == 'all':
|
if dictionary_key == "all":
|
||||||
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
||||||
if not data:
|
if not data:
|
||||||
dispatch.refresh_dictionary()
|
dispatch.refresh_dictionary()
|
||||||
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
||||||
else:
|
else:
|
||||||
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
|
# data = self.queryset.filter(
|
||||||
'color')
|
# 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=data, msg="获取成功")
|
||||||
return SuccessResponse(data=[], msg="获取成功")
|
return SuccessResponse(data=[], msg="获取成功")
|
||||||
|
|
|
@ -20,10 +20,19 @@ class MenuSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
菜单表的简单序列化器
|
菜单表的简单序列化器
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
parent = serializers.SerializerMethodField(read_only=True)
|
||||||
menuPermission = 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):
|
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:
|
if queryset:
|
||||||
return queryset
|
return queryset
|
||||||
else:
|
else:
|
||||||
|
@ -39,6 +48,7 @@ class MenuCreateSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
菜单表的创建序列化器
|
菜单表的创建序列化器
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = serializers.CharField(required=False)
|
name = serializers.CharField(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -51,6 +61,7 @@ class MenuInitSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
递归深度获取数信息(用于生成初始化json文件)
|
递归深度获取数信息(用于生成初始化json文件)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = serializers.CharField(required=False)
|
name = serializers.CharField(required=False)
|
||||||
children = serializers.SerializerMethodField()
|
children = serializers.SerializerMethodField()
|
||||||
menu_button = serializers.SerializerMethodField()
|
menu_button = serializers.SerializerMethodField()
|
||||||
|
@ -65,70 +76,97 @@ class MenuInitSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
def get_menu_button(self, obj: Menu):
|
def get_menu_button(self, obj: Menu):
|
||||||
data = []
|
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:
|
if instance:
|
||||||
data = list(instance.values('name', 'value', 'api', 'method'))
|
data = list(instance.values("name", "value", "api", "method"))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
instance = super().save(**kwargs)
|
instance = super().save(**kwargs)
|
||||||
children = self.initial_data.get('children')
|
children = self.initial_data.get("children")
|
||||||
menu_button = self.initial_data.get('menu_button')
|
menu_button = self.initial_data.get("menu_button")
|
||||||
# 菜单表
|
# 菜单表
|
||||||
if children:
|
if children:
|
||||||
for menu_data in children:
|
for menu_data in children:
|
||||||
menu_data['parent'] = instance.id
|
menu_data["parent"] = instance.id
|
||||||
filter_data = {
|
filter_data = {
|
||||||
"name": menu_data['name'],
|
"name": menu_data["name"],
|
||||||
"web_path": menu_data['web_path'],
|
"web_path": menu_data["web_path"],
|
||||||
"component": menu_data['component'],
|
"component": menu_data["component"],
|
||||||
"component_name": menu_data['component_name'],
|
"component_name": menu_data["component_name"],
|
||||||
}
|
}
|
||||||
instance_obj = Menu.objects.filter(**filter_data).first()
|
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.is_valid(raise_exception=True)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
# 菜单按钮
|
# 菜单按钮
|
||||||
if menu_button:
|
if menu_button:
|
||||||
for menu_button_data in menu_button:
|
for menu_button_data in menu_button:
|
||||||
menu_button_data['menu'] = instance.id
|
menu_button_data["menu"] = instance.id
|
||||||
filter_data = {
|
filter_data = {
|
||||||
"menu": menu_button_data['menu'],
|
"menu": menu_button_data["menu"],
|
||||||
"value": menu_button_data['value']
|
"value": menu_button_data["value"],
|
||||||
}
|
}
|
||||||
instance_obj = MenuButton.objects.filter(**filter_data).first()
|
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.is_valid(raise_exception=True)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Menu
|
model = Menu
|
||||||
fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
|
fields = [
|
||||||
'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
|
"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 = {
|
extra_kwargs = {
|
||||||
'creator': {'write_only': True},
|
"creator": {"write_only": True},
|
||||||
'dept_belong_id': {'write_only': True}
|
"dept_belong_id": {"write_only": True},
|
||||||
}
|
}
|
||||||
read_only_fields = ['id', 'children']
|
read_only_fields = ["id", "children"]
|
||||||
|
|
||||||
|
|
||||||
class WebRouterSerializer(CustomModelSerializer):
|
class WebRouterSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
前端菜单路由的简单序列化器
|
前端菜单路由的简单序列化器
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = serializers.CharField(source="web_path")
|
path = serializers.CharField(source="web_path")
|
||||||
title = serializers.CharField(source="name")
|
title = serializers.CharField(source="name")
|
||||||
|
parent = serializers.SerializerMethodField(read_only=True)
|
||||||
menuPermission = 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):
|
def get_menuPermission(self, instance):
|
||||||
# 判断是否是超级管理员
|
# 判断是否是超级管理员
|
||||||
if self.request.user.is_superuser:
|
if self.request.user.is_superuser:
|
||||||
return MenuButton.objects.values_list('value', flat=True)
|
return MenuButton.objects.values_list("value", flat=True)
|
||||||
else:
|
else:
|
||||||
# 根据当前角色获取权限按钮id集合
|
# 根据当前角色获取权限按钮id集合
|
||||||
permissionIds = self.request.user.role.values_list('permission', 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)
|
queryset = MenuButton.objects.filter(
|
||||||
|
id__in=permissionIds, menu=instance.id
|
||||||
|
).values_list("value", flat=True)
|
||||||
if queryset:
|
if queryset:
|
||||||
return queryset
|
return queryset
|
||||||
else:
|
else:
|
||||||
|
@ -149,21 +187,29 @@ class MenuViewSet(CustomModelViewSet):
|
||||||
retrieve:单例
|
retrieve:单例
|
||||||
destroy:删除
|
destroy:删除
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = Menu.objects.all()
|
queryset = Menu.objects.all()
|
||||||
serializer_class = MenuSerializer
|
serializer_class = MenuSerializer
|
||||||
create_serializer_class = MenuCreateSerializer
|
create_serializer_class = MenuCreateSerializer
|
||||||
update_serializer_class = MenuCreateSerializer
|
update_serializer_class = MenuCreateSerializer
|
||||||
search_fields = ['name', 'status']
|
search_fields = ["name", "status"]
|
||||||
filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog']
|
filter_fields = [
|
||||||
|
"name",
|
||||||
|
"status",
|
||||||
|
"is_link",
|
||||||
|
"visible",
|
||||||
|
"cache",
|
||||||
|
"is_catalog",
|
||||||
|
]
|
||||||
extra_filter_backends = []
|
extra_filter_backends = []
|
||||||
|
|
||||||
@action(methods=['GET'], detail=True, permission_classes=[])
|
@action(methods=["GET"], detail=True, permission_classes=[])
|
||||||
def web_router(self, request):
|
def web_router(self, request):
|
||||||
"""用于前端获取当前角色的路由"""
|
"""用于前端获取当前角色的路由"""
|
||||||
user = request.user
|
user = request.user
|
||||||
queryset = self.queryset.filter(status=1)
|
queryset = self.queryset.filter(status=1)
|
||||||
if not user.is_superuser:
|
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)
|
queryset = Menu.objects.filter(id__in=menuIds, status=1)
|
||||||
serializer = WebRouterSerializer(queryset, many=True, request=request)
|
serializer = WebRouterSerializer(queryset, many=True, request=request)
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
|
|
|
@ -7,12 +7,14 @@ from rest_framework import request
|
||||||
|
|
||||||
from application import settings
|
from application import settings
|
||||||
from dvadmin.system.models import Users
|
from dvadmin.system.models import Users
|
||||||
|
from treebeard.mp_tree import MP_Node
|
||||||
|
|
||||||
|
|
||||||
class CoreInitialize:
|
class CoreInitialize:
|
||||||
"""
|
"""
|
||||||
使用方法:继承此类,重写 run方法,在 run 中调用 save 进行数据初始化
|
使用方法:继承此类,重写 run方法,在 run 中调用 save 进行数据初始化
|
||||||
"""
|
"""
|
||||||
|
|
||||||
creator_id = None
|
creator_id = None
|
||||||
reset = False
|
reset = False
|
||||||
request = request
|
request = request
|
||||||
|
@ -25,13 +27,16 @@ class CoreInitialize:
|
||||||
"""
|
"""
|
||||||
self.reset = reset or self.reset
|
self.reset = reset or self.reset
|
||||||
self.creator_id = creator_id or self.creator_id
|
self.creator_id = creator_id or self.creator_id
|
||||||
self.app = app or ''
|
self.app = app or ""
|
||||||
self.request.user = Users.objects.order_by('create_datetime').first()
|
self.request.user = Users.objects.order_by("create_datetime").first()
|
||||||
|
|
||||||
def init_base(self, Serializer, unique_fields=None):
|
def init_base(self, Serializer, unique_fields=None):
|
||||||
model = Serializer.Meta.model
|
model = Serializer.Meta.model
|
||||||
path_file = os.path.join(apps.get_app_config(self.app.split('.')[-1]).path, 'fixtures',
|
path_file = os.path.join(
|
||||||
f'init_{Serializer.Meta.model._meta.model_name}.json')
|
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):
|
if not os.path.isfile(path_file):
|
||||||
return
|
return
|
||||||
with open(path_file) as f:
|
with open(path_file) as f:
|
||||||
|
@ -44,7 +49,7 @@ class CoreInitialize:
|
||||||
filter_data[field] = data[field]
|
filter_data[field] = data[field]
|
||||||
else:
|
else:
|
||||||
for key, value in data.items():
|
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
|
continue
|
||||||
filter_data[key] = value
|
filter_data[key] = value
|
||||||
instance = model.objects.filter(**filter_data).first()
|
instance = model.objects.filter(**filter_data).first()
|
||||||
|
@ -62,26 +67,33 @@ class CoreInitialize:
|
||||||
settings.INITIALIZE_RESET_LIST.append(obj)
|
settings.INITIALIZE_RESET_LIST.append(obj)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
for ele in data:
|
if MP_Node in obj.__mro__:
|
||||||
m2m_dict = {}
|
obj.load_bulk(data, None, True)
|
||||||
new_data = {}
|
else:
|
||||||
for key, value in ele.items():
|
for ele in data:
|
||||||
# 判断传的 value 为 list 的多对多进行抽离,使用set 进行更新
|
m2m_dict = {}
|
||||||
if isinstance(value, list) and value and isinstance(value[0], int):
|
new_data = {}
|
||||||
m2m_dict[key] = value
|
for key, value in ele.items():
|
||||||
else:
|
# 判断传的 value 为 list 的多对多进行抽离,使用set 进行更新
|
||||||
new_data[key] = value
|
if isinstance(value, list) and value and isinstance(value[0], int):
|
||||||
object, _ = obj.objects.get_or_create(id=ele.get("id"), defaults=new_data)
|
m2m_dict[key] = value
|
||||||
for key, m2m in m2m_dict.items():
|
else:
|
||||||
m2m = list(set(m2m))
|
new_data[key] = value
|
||||||
if m2m and len(m2m) > 0 and m2m[0]:
|
object, _ = obj.objects.get_or_create(
|
||||||
exec(f"""
|
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"""
|
||||||
if object.{key}:
|
if object.{key}:
|
||||||
values_list = object.{key}.all().values_list('id', flat=True)
|
values_list = object.{key}.all().values_list('id', flat=True)
|
||||||
values_list = list(set(list(values_list) + {m2m}))
|
values_list = list(set(list(values_list) + {m2m}))
|
||||||
object.{key}.set(values_list)
|
object.{key}.set(values_list)
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
print(f"初始化完成[{obj._meta.label} => {name}]")
|
print(f"初始化完成[{obj._meta.label} => {name}]")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
raise NotImplementedError('.run() must be overridden')
|
raise NotImplementedError(".run() must be overridden")
|
||||||
|
|
|
@ -23,6 +23,10 @@ class CustomModelSerializer(DynamicFieldsMixin, ModelSerializer):
|
||||||
(1)self.request能获取到rest_framework.request.Request对象
|
(1)self.request能获取到rest_framework.request.Request对象
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# 放空treebeard.mp_tree.MP_Node的继承字段
|
||||||
|
path = serializers.CharField(required=False)
|
||||||
|
depth = serializers.IntegerField(required=False)
|
||||||
|
|
||||||
# 修改人的审计字段名称, 默认modifier, 继承使用时可自定义覆盖
|
# 修改人的审计字段名称, 默认modifier, 继承使用时可自定义覆盖
|
||||||
modifier_field_id = "modifier"
|
modifier_field_id = "modifier"
|
||||||
modifier_name = serializers.SerializerMethodField(read_only=True)
|
modifier_name = serializers.SerializerMethodField(read_only=True)
|
||||||
|
|
|
@ -14,12 +14,19 @@ from rest_framework.decorators import action
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from dvadmin.utils.filters import DataLevelPermissionsFilter
|
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.json_response import SuccessResponse, ErrorResponse, DetailResponse
|
||||||
from dvadmin.utils.permission import CustomPermission
|
from dvadmin.utils.permission import CustomPermission
|
||||||
from django_restql.mixins import QueryArgumentsMixin
|
from django_restql.mixins import QueryArgumentsMixin
|
||||||
|
from treebeard.models import Node
|
||||||
|
|
||||||
class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixin,QueryArgumentsMixin):
|
|
||||||
|
class CustomModelViewSet(
|
||||||
|
ModelViewSet, ImportSerializerMixin, ExportSerializerMixin, QueryArgumentsMixin
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
自定义的ModelViewSet:
|
自定义的ModelViewSet:
|
||||||
统一标准的返回格式;新增,查询,修改可使用不同序列化器
|
统一标准的返回格式;新增,查询,修改可使用不同序列化器
|
||||||
|
@ -29,11 +36,12 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
|
||||||
(4)import_field_dict={} 导入时的字段字典 {model值: model的label}
|
(4)import_field_dict={} 导入时的字段字典 {model值: model的label}
|
||||||
(5)export_field_label = [] 导出时的字段
|
(5)export_field_label = [] 导出时的字段
|
||||||
"""
|
"""
|
||||||
|
|
||||||
values_queryset = None
|
values_queryset = None
|
||||||
ordering_fields = '__all__'
|
ordering_fields = "__all__"
|
||||||
create_serializer_class = None
|
create_serializer_class = None
|
||||||
update_serializer_class = None
|
update_serializer_class = None
|
||||||
filter_fields = '__all__'
|
filter_fields = "__all__"
|
||||||
search_fields = ()
|
search_fields = ()
|
||||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||||
permission_classes = [CustomPermission]
|
permission_classes = [CustomPermission]
|
||||||
|
@ -41,12 +49,14 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
|
||||||
export_field_label = []
|
export_field_label = []
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
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)
|
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self, 'values_queryset', None):
|
if getattr(self, "values_queryset", None):
|
||||||
return self.values_queryset
|
return self.values_queryset
|
||||||
return super().get_queryset()
|
return super().get_queryset()
|
||||||
|
|
||||||
|
@ -60,6 +70,15 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
serializer = self.get_serializer(data=request.data, request=request)
|
serializer = self.get_serializer(data=request.data, request=request)
|
||||||
serializer.is_valid(raise_exception=True)
|
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)
|
self.perform_create(serializer)
|
||||||
return DetailResponse(data=serializer.data, msg="新增成功")
|
return DetailResponse(data=serializer.data, msg="新增成功")
|
||||||
|
|
||||||
|
@ -78,13 +97,15 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
|
||||||
return DetailResponse(data=serializer.data, msg="获取成功")
|
return DetailResponse(data=serializer.data, msg="获取成功")
|
||||||
|
|
||||||
def update(self, request, *args, **kwargs):
|
def update(self, request, *args, **kwargs):
|
||||||
partial = kwargs.pop('partial', False)
|
partial = kwargs.pop("partial", False)
|
||||||
instance = self.get_object()
|
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)
|
serializer.is_valid(raise_exception=True)
|
||||||
self.perform_update(serializer)
|
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
|
# If 'prefetch_related' has been applied to a queryset, we need to
|
||||||
# forcibly invalidate the prefetch cache on the instance.
|
# forcibly invalidate the prefetch cache on the instance.
|
||||||
instance._prefetched_objects_cache = {}
|
instance._prefetched_objects_cache = {}
|
||||||
|
@ -95,17 +116,20 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
|
||||||
self.perform_destroy(instance)
|
self.perform_destroy(instance)
|
||||||
return DetailResponse(data=[], msg="删除成功")
|
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(
|
||||||
@swagger_auto_schema(request_body=openapi.Schema(
|
request_body=openapi.Schema(
|
||||||
type=openapi.TYPE_OBJECT,
|
type=openapi.TYPE_OBJECT, required=["keys"], properties={"keys": keys}
|
||||||
required=['keys'],
|
),
|
||||||
properties={'keys': keys}
|
operation_summary="批量删除",
|
||||||
), operation_summary='批量删除')
|
)
|
||||||
@action(methods=['delete'],detail=False)
|
@action(methods=["delete"], detail=False)
|
||||||
def multiple_delete(self,request,*args,**kwargs):
|
def multiple_delete(self, request, *args, **kwargs):
|
||||||
request_data = request.data
|
request_data = request.data
|
||||||
keys = request_data.get('keys',None)
|
keys = request_data.get("keys", None)
|
||||||
if keys:
|
if keys:
|
||||||
self.get_queryset().filter(id__in=keys).delete()
|
self.get_queryset().filter(id__in=keys).delete()
|
||||||
return SuccessResponse(data=[], msg="删除成功")
|
return SuccessResponse(data=[], msg="删除成功")
|
||||||
|
|
|
@ -41,3 +41,4 @@ urllib3==1.26.6
|
||||||
user-agents==2.2.0
|
user-agents==2.2.0
|
||||||
whitenoise==5.3.0
|
whitenoise==5.3.0
|
||||||
openpyxl==3.0.9
|
openpyxl==3.0.9
|
||||||
|
django-treebeard>=4.5.1
|
|
@ -379,7 +379,7 @@ export const crudOptions = (vm) => {
|
||||||
search: {
|
search: {
|
||||||
disabled: false
|
disabled: false
|
||||||
},
|
},
|
||||||
width: 50,
|
width: 60,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
dict: {
|
dict: {
|
||||||
data: vm.dictionary('button_whether_bool')
|
data: vm.dictionary('button_whether_bool')
|
||||||
|
|
824
web/yarn.lock
824
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue