优化:字段长度优化
parent
03455ba9d0
commit
d31d9fc3ca
|
@ -3,6 +3,7 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from dvadmin.utils.validator import CustomValidationError
|
||||||
|
|
||||||
dispatch_db_type = getattr(settings, 'DISPATCH_DB_TYPE', 'memory') # redis
|
dispatch_db_type = getattr(settings, 'DISPATCH_DB_TYPE', 'memory') # redis
|
||||||
|
|
||||||
|
@ -243,6 +244,22 @@ def get_system_config_values(key, schema_name=None):
|
||||||
return system_config.get(key)
|
return system_config.get(key)
|
||||||
|
|
||||||
|
|
||||||
|
def get_system_config_values_to_dict(key, schema_name=None):
|
||||||
|
"""
|
||||||
|
获取系统配置数据并转换为字典 **仅限于数组类型系统配置
|
||||||
|
:param key: 对应系统配置的key值(字典编号)
|
||||||
|
:param schema_name: 对应系统配置的租户schema_name值
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
values_dict = {}
|
||||||
|
config_values = get_system_config_values(key, schema_name)
|
||||||
|
if not isinstance(config_values, list):
|
||||||
|
raise CustomValidationError("该方式仅限于数组类型系统配置")
|
||||||
|
for ele in get_system_config_values(key, schema_name):
|
||||||
|
values_dict[ele.get('key')] = ele.get('value')
|
||||||
|
return values_dict
|
||||||
|
|
||||||
|
|
||||||
def get_system_config_label(key, name, schema_name=None):
|
def get_system_config_label(key, name, schema_name=None):
|
||||||
"""
|
"""
|
||||||
获取获取系统配置label值
|
获取获取系统配置label值
|
||||||
|
|
|
@ -13,8 +13,11 @@ STATUS_CHOICES = (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Users(CoreModel,AbstractUser):
|
class Users(CoreModel, AbstractUser):
|
||||||
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号")
|
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号",
|
||||||
|
help_text="用户账号")
|
||||||
|
employee_no = models.CharField(max_length=150, unique=True, db_index=True, null=True, blank=True,
|
||||||
|
verbose_name="工号", help_text="工号")
|
||||||
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, 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="电话")
|
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="头像")
|
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
|
||||||
|
@ -34,8 +37,10 @@ class Users(CoreModel,AbstractUser):
|
||||||
user_type = models.IntegerField(
|
user_type = models.IntegerField(
|
||||||
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
|
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
|
||||||
)
|
)
|
||||||
post = models.ManyToManyField(to="Post",blank=True, verbose_name="关联岗位", db_constraint=False, help_text="关联岗位")
|
post = models.ManyToManyField(to="Post", blank=True, verbose_name="关联岗位", db_constraint=False,
|
||||||
role = models.ManyToManyField(to="Role", blank=True,verbose_name="关联角色", db_constraint=False, help_text="关联角色")
|
help_text="关联岗位")
|
||||||
|
role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False,
|
||||||
|
help_text="关联角色")
|
||||||
dept = models.ForeignKey(
|
dept = models.ForeignKey(
|
||||||
to="Dept",
|
to="Dept",
|
||||||
verbose_name="所属部门",
|
verbose_name="所属部门",
|
||||||
|
@ -45,7 +50,8 @@ class Users(CoreModel,AbstractUser):
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="关联部门",
|
help_text="关联部门",
|
||||||
)
|
)
|
||||||
last_token = models.CharField(max_length=255,null=True,blank=True, verbose_name="最后一次登录Token", help_text="最后一次登录Token")
|
last_token = models.CharField(max_length=255, null=True, blank=True, verbose_name="最后一次登录Token",
|
||||||
|
help_text="最后一次登录Token")
|
||||||
|
|
||||||
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())
|
||||||
|
@ -87,9 +93,11 @@ 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(to="Dept", verbose_name="数据权限-关联部门", db_constraint=False,
|
||||||
|
help_text="数据权限-关联部门")
|
||||||
menu = models.ManyToManyField(to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单")
|
menu = models.ManyToManyField(to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单")
|
||||||
permission = models.ManyToManyField(
|
permission = models.ManyToManyField(
|
||||||
to="MenuButton", verbose_name="关联菜单的接口按钮", db_constraint=False, help_text="关联菜单的接口按钮"
|
to="MenuButton", verbose_name="关联菜单的接口按钮", db_constraint=False, help_text="关联菜单的接口按钮"
|
||||||
|
@ -104,7 +112,8 @@ class Role(CoreModel):
|
||||||
|
|
||||||
class Dept(CoreModel):
|
class Dept(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,null=True,blank=True, verbose_name="关联字符", help_text="关联字符")
|
key = models.CharField(max_length=64, unique=True, null=True, blank=True, 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(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="联系电话")
|
phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")
|
||||||
|
@ -168,10 +177,12 @@ class Menu(CoreModel):
|
||||||
is_catalog = 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="路由地址")
|
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 = 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="组件名称")
|
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="菜单状态")
|
status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")
|
||||||
cache = models.BooleanField(default=False, 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="侧边栏中是否显示")
|
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
|
||||||
|
help_text="侧边栏中是否显示")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "system_menu"
|
db_table = table_prefix + "system_menu"
|
||||||
|
@ -198,7 +209,8 @@ 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"
|
||||||
|
@ -219,7 +231,8 @@ class Dictionary(CoreModel):
|
||||||
(7, "images"),
|
(7, "images"),
|
||||||
)
|
)
|
||||||
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
|
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="字典编号/实际值")
|
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号",
|
||||||
|
help_text="字典编号/实际值")
|
||||||
parent = models.ForeignKey(
|
parent = models.ForeignKey(
|
||||||
to="self",
|
to="self",
|
||||||
related_name="sublist",
|
related_name="sublist",
|
||||||
|
@ -232,7 +245,8 @@ class Dictionary(CoreModel):
|
||||||
)
|
)
|
||||||
type = models.IntegerField(choices=TYPE_LIST, default=0, 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="颜色")
|
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值,用来做具体值存放")
|
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(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
|
||||||
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
|
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
|
||||||
|
@ -254,14 +268,20 @@ class Dictionary(CoreModel):
|
||||||
|
|
||||||
|
|
||||||
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(max_length=64, verbose_name="请求模块", null=True, blank=True,
|
||||||
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址")
|
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_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_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_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_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True,
|
||||||
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True, help_text="请求浏览器")
|
help_text="请求ip地址")
|
||||||
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码")
|
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="操作系统")
|
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="返回信息")
|
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="响应状态")
|
||||||
|
@ -302,7 +322,8 @@ class FileList(CoreModel):
|
||||||
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(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乡级)")
|
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="是否启用")
|
||||||
|
@ -335,8 +356,10 @@ 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(default=0, verbose_name="接口请求方法", null=True, blank=True,
|
||||||
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", 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"
|
||||||
|
@ -356,8 +379,8 @@ class SystemConfig(CoreModel):
|
||||||
help_text="父级",
|
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=100, verbose_name="键", help_text="键", db_index=True)
|
key = models.CharField(max_length=200, verbose_name="键", help_text="键", db_index=True)
|
||||||
value = models.JSONField(max_length=200, verbose_name="值", help_text="值", null=True, blank=True)
|
value = models.JSONField(max_length=500, 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(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
||||||
|
@ -383,7 +406,7 @@ class SystemConfig(CoreModel):
|
||||||
choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True
|
choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True
|
||||||
)
|
)
|
||||||
rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则")
|
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="提示信息")
|
placeholder = models.CharField(max_length=100, 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="配置")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -415,8 +438,15 @@ class SystemConfig(CoreModel):
|
||||||
|
|
||||||
|
|
||||||
class LoginLog(CoreModel):
|
class LoginLog(CoreModel):
|
||||||
LOGIN_TYPE_CHOICES = ((1, "普通登录"), (2, "微信扫码登录"), (3, "飞书扫码登录"), (4, "钉钉扫码登录"))
|
LOGIN_TYPE_CHOICES = (
|
||||||
username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")
|
(1, "普通登录"),
|
||||||
|
(2, "普通扫码登录"),
|
||||||
|
(3, "微信扫码登录"),
|
||||||
|
(4, "飞书扫码登录"),
|
||||||
|
(5, "钉钉扫码登录"),
|
||||||
|
(6, "短信登录")
|
||||||
|
)
|
||||||
|
username = models.CharField(max_length=150, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")
|
||||||
ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip")
|
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信息")
|
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="浏览器名")
|
browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名")
|
||||||
|
@ -428,11 +458,13 @@ class LoginLog(CoreModel):
|
||||||
district = 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="运营商")
|
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="区域代码")
|
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_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="简称")
|
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="经度")
|
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="纬度")
|
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="登录类型")
|
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"
|
||||||
|
@ -442,10 +474,12 @@ class LoginLog(CoreModel):
|
||||||
|
|
||||||
|
|
||||||
class MessageCenter(CoreModel):
|
class MessageCenter(CoreModel):
|
||||||
title = models.CharField(max_length=100,verbose_name="标题",help_text="标题")
|
title = models.CharField(max_length=100, verbose_name="标题", help_text="标题")
|
||||||
content = models.TextField(verbose_name="内容",help_text="内容")
|
content = models.TextField(verbose_name="内容", help_text="内容")
|
||||||
target_type=models.IntegerField(default=0,verbose_name="目标类型",help_text="目标类型")
|
target_type = models.IntegerField(default=0, verbose_name="目标类型", help_text="目标类型")
|
||||||
target_user = models.ManyToManyField(to=Users,related_name='user',through='MessageCenterTargetUser', through_fields=('messagecenter','users'),blank=True,verbose_name="目标用户",help_text="目标用户")
|
target_user = models.ManyToManyField(to=Users, related_name='user', through='MessageCenterTargetUser',
|
||||||
|
through_fields=('messagecenter', 'users'), blank=True, verbose_name="目标用户",
|
||||||
|
help_text="目标用户")
|
||||||
target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,
|
target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,
|
||||||
verbose_name="目标部门", help_text="目标部门")
|
verbose_name="目标部门", help_text="目标部门")
|
||||||
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
|
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
|
||||||
|
@ -457,10 +491,13 @@ class MessageCenter(CoreModel):
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ("-create_datetime",)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
||||||
class MessageCenterTargetUser(CoreModel):
|
class MessageCenterTargetUser(CoreModel):
|
||||||
users = models.ForeignKey(Users,related_name="target_user", on_delete=models.CASCADE,db_constraint=False,verbose_name="关联用户表",help_text="关联用户表")
|
users = models.ForeignKey(Users, related_name="target_user", on_delete=models.CASCADE, db_constraint=False,
|
||||||
messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE,db_constraint=False,verbose_name="关联消息中心表",help_text="关联消息中心表")
|
verbose_name="关联用户表", help_text="关联用户表")
|
||||||
is_read = models.BooleanField(default=False,blank=True,null=True,verbose_name="是否已读",help_text="是否已读")
|
messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE, db_constraint=False,
|
||||||
|
verbose_name="关联消息中心表", help_text="关联消息中心表")
|
||||||
|
is_read = models.BooleanField(default=False, blank=True, null=True, verbose_name="是否已读", help_text="是否已读")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "message_center_target_user"
|
db_table = table_prefix + "message_center_target_user"
|
||||||
|
|
|
@ -70,6 +70,7 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||||
default_error_messages = {"no_active_account": _("账号/密码错误")}
|
default_error_messages = {"no_active_account": _("账号/密码错误")}
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
|
||||||
captcha = self.initial_data.get("captcha", None)
|
captcha = self.initial_data.get("captcha", None)
|
||||||
if dispatch.get_system_config_values("base.captcha_state"):
|
if dispatch.get_system_config_values("base.captcha_state"):
|
||||||
if captcha is None:
|
if captcha is None:
|
||||||
|
|
|
@ -7,12 +7,15 @@
|
||||||
@Remark: 公共基础model类
|
@Remark: 公共基础model类
|
||||||
"""
|
"""
|
||||||
import uuid
|
import uuid
|
||||||
|
from datetime import date, timedelta
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.db import models
|
from django.db import models, connection, ProgrammingError
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
from application import settings
|
from application import settings
|
||||||
|
from application.dispatch import is_tenants_mode
|
||||||
|
|
||||||
table_prefix = settings.TABLE_PREFIX # 数据库表名前缀
|
table_prefix = settings.TABLE_PREFIX # 数据库表名前缀
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,10 +43,17 @@ class SoftDeleteManager(models.Manager):
|
||||||
return SoftDeleteQuerySet(self.model, using=self._db).exclude(is_deleted=False)
|
return SoftDeleteQuerySet(self.model, using=self._db).exclude(is_deleted=False)
|
||||||
return SoftDeleteQuerySet(self.model).exclude(is_deleted=True)
|
return SoftDeleteQuerySet(self.model).exclude(is_deleted=True)
|
||||||
|
|
||||||
def get_by_natural_key(self,name):
|
def get_by_natural_key(self, name):
|
||||||
return SoftDeleteQuerySet(self.model).get(username=name)
|
return SoftDeleteQuerySet(self.model).get(username=name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_month_range(start_day, end_day):
|
||||||
|
months = (end_day.year - start_day.year) * 12 + end_day.month - start_day.month
|
||||||
|
month_range = ['%s-%s-01' % (start_day.year + mon // 12, str(mon % 12 + 1).zfill(2))
|
||||||
|
for mon in range(start_day.month - 1, start_day.month + months)]
|
||||||
|
return month_range
|
||||||
|
|
||||||
|
|
||||||
class SoftDeleteModel(models.Model):
|
class SoftDeleteModel(models.Model):
|
||||||
"""
|
"""
|
||||||
软删除模型
|
软删除模型
|
||||||
|
@ -73,10 +83,13 @@ class CoreModel(models.Model):
|
||||||
id = models.BigAutoField(primary_key=True, help_text="Id", verbose_name="Id")
|
id = models.BigAutoField(primary_key=True, help_text="Id", verbose_name="Id")
|
||||||
description = models.CharField(max_length=255, verbose_name="描述", null=True, blank=True, help_text="描述")
|
description = models.CharField(max_length=255, verbose_name="描述", null=True, blank=True, help_text="描述")
|
||||||
creator = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_query_name='creator_query', null=True,
|
creator = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_query_name='creator_query', null=True,
|
||||||
verbose_name='创建人', help_text="创建人", on_delete=models.SET_NULL, db_constraint=False)
|
verbose_name='创建人', help_text="创建人", on_delete=models.SET_NULL,
|
||||||
|
db_constraint=False)
|
||||||
modifier = models.CharField(max_length=255, null=True, blank=True, help_text="修改人", verbose_name="修改人")
|
modifier = models.CharField(max_length=255, null=True, blank=True, help_text="修改人", verbose_name="修改人")
|
||||||
dept_belong_id = models.CharField(max_length=255, help_text="数据归属部门", null=True, blank=True, verbose_name="数据归属部门")
|
dept_belong_id = models.CharField(max_length=255, help_text="数据归属部门", null=True, blank=True,
|
||||||
update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间", verbose_name="修改时间")
|
verbose_name="数据归属部门")
|
||||||
|
update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间",
|
||||||
|
verbose_name="修改时间")
|
||||||
create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间",
|
create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间",
|
||||||
verbose_name="创建时间")
|
verbose_name="创建时间")
|
||||||
|
|
||||||
|
@ -86,6 +99,113 @@ class CoreModel(models.Model):
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class AddPostgresPartitionedBase:
|
||||||
|
"""
|
||||||
|
pgsql表分表基类
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_hash_partition(cls, number=36):
|
||||||
|
"""
|
||||||
|
创建分区表
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if cls.PartitioningMeta.method != 'hash':
|
||||||
|
raise ProgrammingError("表分区错误,无法进行分区")
|
||||||
|
schema_editor = connection.schema_editor()
|
||||||
|
if is_tenants_mode():
|
||||||
|
schema_editor.sql_add_hash_partition = f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES WITH (MODULUS %s, REMAINDER %s)'
|
||||||
|
for item in range(number):
|
||||||
|
try:
|
||||||
|
schema_editor.add_hash_partition(
|
||||||
|
model=cls,
|
||||||
|
name="_" + str(item),
|
||||||
|
modulus=number,
|
||||||
|
remainder=item,
|
||||||
|
)
|
||||||
|
except ProgrammingError as e:
|
||||||
|
print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n'))
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_range_day_partition(cls, day=7):
|
||||||
|
"""
|
||||||
|
按照创建时间"天"分表
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if cls.PartitioningMeta.method != 'range':
|
||||||
|
raise ProgrammingError("表分区错误,无法进行分区")
|
||||||
|
day_before = date.today().strftime("%Y-%m-%d")
|
||||||
|
schema_editor = connection.schema_editor()
|
||||||
|
if is_tenants_mode():
|
||||||
|
schema_editor.sql_add_range_partition = (
|
||||||
|
f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES FROM (%s) TO (%s)'
|
||||||
|
)
|
||||||
|
for index in range(day):
|
||||||
|
try:
|
||||||
|
day_following = (date.today() + timedelta(days=index + 1)).strftime("%Y-%m-%d")
|
||||||
|
schema_editor.add_range_partition(
|
||||||
|
model=cls,
|
||||||
|
name=f"{day_before}_{day_following}",
|
||||||
|
from_values=day_before,
|
||||||
|
to_values=day_following,
|
||||||
|
)
|
||||||
|
day_before = day_following
|
||||||
|
except ProgrammingError as e:
|
||||||
|
print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n'))
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_range_month_partition(cls, start_date, end_date):
|
||||||
|
"""
|
||||||
|
按照创建时间"月"分表
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if cls.PartitioningMeta.method != 'range':
|
||||||
|
raise ProgrammingError("表分区错误,无法进行分区")
|
||||||
|
range_month_partition_list = get_month_range(start_date, end_date)
|
||||||
|
schema_editor = connection.schema_editor()
|
||||||
|
if is_tenants_mode():
|
||||||
|
schema_editor.sql_add_range_partition = (
|
||||||
|
f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES FROM (%s) TO (%s)'
|
||||||
|
)
|
||||||
|
for index, ele in enumerate(range_month_partition_list):
|
||||||
|
if index == 0:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
schema_editor.add_range_partition(
|
||||||
|
model=cls,
|
||||||
|
name=f"{range_month_partition_list[index - 1][:-3]}_{ele[:-3]}",
|
||||||
|
from_values=range_month_partition_list[index - 1],
|
||||||
|
to_values=ele,
|
||||||
|
)
|
||||||
|
except ProgrammingError as e:
|
||||||
|
print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n'))
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_list_partition(cls, unique_value):
|
||||||
|
"""
|
||||||
|
按照某个值进行分区
|
||||||
|
:param unique_value:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if cls.PartitioningMeta.method != 'list':
|
||||||
|
raise ProgrammingError("表分区错误,无法进行分区")
|
||||||
|
schema_editor = connection.schema_editor()
|
||||||
|
if is_tenants_mode():
|
||||||
|
schema_editor.sql_add_list_partition = (
|
||||||
|
f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES IN (%s)'
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
schema_editor.add_list_partition(
|
||||||
|
model=cls,
|
||||||
|
name=f"_{unique_value}",
|
||||||
|
values=[unique_value],
|
||||||
|
)
|
||||||
|
except ProgrammingError as e:
|
||||||
|
print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n'))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def get_all_models_objects(model_name=None):
|
def get_all_models_objects(model_name=None):
|
||||||
|
|
|
@ -202,7 +202,7 @@ def get_ip_analysis(ip):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def save_login_log(request):
|
def save_login_log(request, login_type=1):
|
||||||
"""
|
"""
|
||||||
保存登录日志
|
保存登录日志
|
||||||
:return:
|
:return:
|
||||||
|
@ -214,6 +214,7 @@ def save_login_log(request):
|
||||||
analysis_data['agent'] = str(parse(request.META['HTTP_USER_AGENT']))
|
analysis_data['agent'] = str(parse(request.META['HTTP_USER_AGENT']))
|
||||||
analysis_data['browser'] = get_browser(request)
|
analysis_data['browser'] = get_browser(request)
|
||||||
analysis_data['os'] = get_os(request)
|
analysis_data['os'] = get_os(request)
|
||||||
|
analysis_data['login_type'] = login_type
|
||||||
analysis_data['creator_id'] = request.user.id
|
analysis_data['creator_id'] = request.user.id
|
||||||
analysis_data['dept_belong_id'] = getattr(request.user, 'dept_id', '')
|
analysis_data['dept_belong_id'] = getattr(request.user, 'dept_id', '')
|
||||||
LoginLog.objects.create(**analysis_data)
|
LoginLog.objects.create(**analysis_data)
|
||||||
|
|
Loading…
Reference in New Issue