294 lines
10 KiB
Python
294 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
@author: 猿小天
|
||
@contact: QQ:1638245306
|
||
@Created on: 2021/5/31 031 22:08
|
||
@Remark: 公共基础model类
|
||
"""
|
||
from datetime import datetime
|
||
from importlib import import_module
|
||
|
||
from application import settings
|
||
from django.apps import apps
|
||
from django.conf import settings
|
||
from django.db import models
|
||
from rest_framework.request import Request
|
||
|
||
table_prefix = settings.TABLE_PREFIX # 数据库表名前缀
|
||
|
||
|
||
class SoftDeleteQuerySet(models.QuerySet):
|
||
pass
|
||
|
||
|
||
class SoftDeleteManager(models.Manager):
|
||
"""支持软删除"""
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
self.__add_is_del_filter = False
|
||
super(SoftDeleteManager, self).__init__(*args, **kwargs)
|
||
|
||
def filter(self, *args, **kwargs):
|
||
# 考虑是否主动传入is_deleted
|
||
if not kwargs.get('is_deleted') is None:
|
||
self.__add_is_del_filter = True
|
||
return super(SoftDeleteManager, self).filter(*args, **kwargs)
|
||
|
||
def get_queryset(self):
|
||
if self.__add_is_del_filter:
|
||
return SoftDeleteQuerySet(self.model, using=self._db).exclude(is_deleted=False)
|
||
return SoftDeleteQuerySet(self.model).exclude(is_deleted=True)
|
||
|
||
def get_by_natural_key(self, name):
|
||
return SoftDeleteQuerySet(self.model).get(username=name)
|
||
|
||
|
||
class SoftDeleteModel(models.Model):
|
||
"""
|
||
软删除模型
|
||
一旦继承,就将开启软删除
|
||
"""
|
||
is_deleted = models.BooleanField(verbose_name="是否软删除", help_text='是否软删除', default=False, db_index=True)
|
||
objects = SoftDeleteManager()
|
||
|
||
class Meta:
|
||
abstract = True
|
||
verbose_name = '软删除模型'
|
||
verbose_name_plural = verbose_name
|
||
|
||
def delete(self, using=None, soft_delete=True, *args, **kwargs):
|
||
"""
|
||
重写删除方法,直接开启软删除
|
||
"""
|
||
if soft_delete:
|
||
self.is_deleted = True
|
||
self.save(using=using)
|
||
# 级联软删除关联对象
|
||
for related_object in self._meta.related_objects:
|
||
related_model = getattr(self, related_object.get_accessor_name())
|
||
# 处理一对多和多对多的关联对象
|
||
if related_object.one_to_many or related_object.many_to_many:
|
||
related_objects = related_model.all()
|
||
elif related_object.one_to_one:
|
||
related_objects = [related_model]
|
||
else:
|
||
continue
|
||
|
||
for obj in related_objects:
|
||
obj.delete(soft_delete=True)
|
||
else:
|
||
super().delete(using=using, *args, **kwargs)
|
||
|
||
|
||
class CoreModelManager(models.Manager):
|
||
def get_queryset(self):
|
||
is_deleted = getattr(self.model, 'is_soft_delete', False)
|
||
flow_work_status = getattr(self.model, 'flow_work_status', False)
|
||
queryset = super().get_queryset()
|
||
if flow_work_status:
|
||
queryset = queryset.filter(flow_work_status=1)
|
||
if is_deleted:
|
||
queryset = queryset.filter(is_deleted=False)
|
||
return queryset
|
||
def create(self,request: Request=None, **kwargs):
|
||
data = {**kwargs}
|
||
if request:
|
||
request_user = request.user
|
||
data["creator"] = request_user
|
||
data["modifier"] = request_user.id
|
||
data["dept_belong_id"] = request_user.dept_id
|
||
# 调用父类的create方法执行实际的创建操作
|
||
return super().create(**data)
|
||
|
||
class CoreModel(models.Model):
|
||
"""
|
||
核心标准抽象模型模型,可直接继承使用
|
||
增加审计字段, 覆盖字段时, 字段名称请勿修改, 必须统一审计字段名称
|
||
"""
|
||
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="描述")
|
||
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)
|
||
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="数据归属部门")
|
||
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="创建时间",
|
||
verbose_name="创建时间")
|
||
objects = CoreModelManager()
|
||
all_objects = models.Manager()
|
||
class Meta:
|
||
abstract = True
|
||
verbose_name = '核心模型'
|
||
verbose_name_plural = verbose_name
|
||
|
||
def get_request_user(self, request: Request):
|
||
if getattr(request, "user", None):
|
||
return request.user
|
||
return None
|
||
|
||
def get_request_user_id(self, request: Request):
|
||
if getattr(request, "user", None):
|
||
return getattr(request.user, "id", None)
|
||
return None
|
||
|
||
def get_request_user_name(self, request: Request):
|
||
if getattr(request, "user", None):
|
||
return getattr(request.user, "name", None)
|
||
return None
|
||
|
||
def get_request_user_username(self, request: Request):
|
||
if getattr(request, "user", None):
|
||
return getattr(request.user, "username", None)
|
||
return None
|
||
|
||
def common_insert_data(self, request: Request):
|
||
data = {
|
||
'create_datetime': datetime.now(),
|
||
'creator': self.get_request_user(request)
|
||
}
|
||
return {**data, **self.common_update_data(request)}
|
||
|
||
def common_update_data(self, request: Request):
|
||
return {
|
||
'update_datetime': datetime.now(),
|
||
'modifier': self.get_request_user_username(request)
|
||
}
|
||
|
||
exclude_fields = [
|
||
'_state',
|
||
'pk',
|
||
'id',
|
||
'create_datetime',
|
||
'update_datetime',
|
||
'creator',
|
||
'creator_id',
|
||
'creator_pk',
|
||
'creator_name',
|
||
'modifier',
|
||
'modifier_id',
|
||
'modifier_pk',
|
||
'modifier_name',
|
||
'dept_belong_id',
|
||
]
|
||
|
||
def get_exclude_fields(self):
|
||
return self.exclude_fields
|
||
|
||
def get_all_fields(self):
|
||
return self._meta.fields
|
||
|
||
def get_all_fields_names(self):
|
||
return [field.name for field in self.get_all_fields()]
|
||
|
||
def get_need_fields_names(self):
|
||
return [field.name for field in self.get_all_fields() if field.name not in self.exclude_fields]
|
||
|
||
def to_data(self):
|
||
"""将模型转化为字典(去除不包含字段)(注意与to_dict_data区分)。
|
||
"""
|
||
res = {}
|
||
for field in self.get_need_fields_names():
|
||
field_value = getattr(self, field)
|
||
res[field] = field_value.id if (issubclass(field_value.__class__, CoreModel)) else field_value
|
||
return res
|
||
|
||
@property
|
||
def DATA(self):
|
||
return self.to_data()
|
||
|
||
def to_dict_data(self):
|
||
"""需要导出的字段(去除不包含字段)(注意与to_data区分)
|
||
"""
|
||
return {field: getattr(self, field) for field in self.get_need_fields_names()}
|
||
|
||
@property
|
||
def DICT_DATA(self):
|
||
return self.to_dict_data()
|
||
|
||
def insert(self, request):
|
||
"""插入模型
|
||
"""
|
||
assert self.pk is None, f'模型{self.__class__.__name__}还没有保存到数据中,不能手动指定ID'
|
||
validated_data = {**self.common_insert_data(request), **self.DICT_DATA}
|
||
return self.__class__._default_manager.create(**validated_data)
|
||
|
||
def update(self, request, update_data: dict[str, any] = None):
|
||
"""更新模型
|
||
"""
|
||
assert isinstance(update_data, dict), 'update_data必须为字典'
|
||
validated_data = {**self.common_insert_data(request), **update_data}
|
||
for key, value in validated_data.items():
|
||
# 不允许修改id,pk,uuid字段
|
||
if key in ['id', 'pk', 'uuid']:
|
||
continue
|
||
if hasattr(self, key):
|
||
setattr(self, key, value)
|
||
self.save()
|
||
return self
|
||
|
||
|
||
def get_all_models_objects(model_name=None):
|
||
"""
|
||
获取所有 models 对象
|
||
:return: {}
|
||
"""
|
||
settings.ALL_MODELS_OBJECTS = {}
|
||
if not settings.ALL_MODELS_OBJECTS:
|
||
all_models = apps.get_models()
|
||
for item in list(all_models):
|
||
table = {"tableName": item._meta.verbose_name, "table": item.__name__, "tableFields": []}
|
||
for field in item._meta.fields:
|
||
fields = {"title": field.verbose_name, "field": field.name}
|
||
table['tableFields'].append(fields)
|
||
settings.ALL_MODELS_OBJECTS.setdefault(item.__name__, {"table": table, "object": item})
|
||
if model_name:
|
||
return settings.ALL_MODELS_OBJECTS[model_name] or {}
|
||
return settings.ALL_MODELS_OBJECTS or {}
|
||
|
||
|
||
def get_model_from_app(app_name):
|
||
"""获取模型里的字段"""
|
||
model_module = import_module(app_name + '.models')
|
||
exclude_models = getattr(model_module, 'exclude_models', [])
|
||
filter_model = [
|
||
value for key, value in model_module.__dict__.items()
|
||
if key != 'CoreModel'
|
||
and isinstance(value, type)
|
||
and issubclass(value, models.Model)
|
||
and key not in exclude_models
|
||
]
|
||
model_list = []
|
||
for model in filter_model:
|
||
if model.__name__ == 'AbstractUser':
|
||
continue
|
||
fields = [{'title': field.verbose_name, 'name': field.name, 'object': field} for field in model._meta.fields]
|
||
model_list.append({'app': app_name, 'verbose': model._meta.verbose_name, 'model': model.__name__, 'object': model, 'fields': fields})
|
||
return model_list
|
||
|
||
|
||
def get_custom_app_models(app_name=None):
|
||
"""
|
||
获取所有项目下的app里的models
|
||
"""
|
||
if app_name:
|
||
return get_model_from_app(app_name)
|
||
all_apps = apps.get_app_configs()
|
||
res = []
|
||
for app in all_apps:
|
||
if app.name.startswith('django'):
|
||
continue
|
||
if app.name in settings.COLUMN_EXCLUDE_APPS:
|
||
continue
|
||
try:
|
||
all_models = get_model_from_app(app.name)
|
||
if all_models:
|
||
for model in all_models:
|
||
res.append(model)
|
||
except Exception as e:
|
||
pass
|
||
return res
|