This commit is contained in:
sheng
2023-07-25 15:25:57 +08:00
parent 8f57a240db
commit 7ccbcebe77
373 changed files with 41578 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2022/1/1 001 9:34
@Remark:
"""
from dvadmin.system.models import ApiWhiteList
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class ApiWhiteListSerializer(CustomModelSerializer):
"""
接口白名单-序列化器
"""
class Meta:
model = ApiWhiteList
fields = "__all__"
read_only_fields = ["id"]
class ApiWhiteListViewSet(CustomModelViewSet):
"""
接口白名单
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = ApiWhiteList.objects.all()
serializer_class = ApiWhiteListSerializer
# permission_classes = []

View File

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
from django.db.models import Q
from rest_framework import serializers
from dvadmin.system.models import Area
from dvadmin.utils.json_response import SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class AreaSerializer(CustomModelSerializer):
"""
地区-序列化器
"""
pcode_count = serializers.SerializerMethodField(read_only=True)
hasChild = serializers.SerializerMethodField()
def get_pcode_count(self, instance: Area):
return Area.objects.filter(pcode=instance).count()
def get_hasChild(self, instance):
hasChild = Area.objects.filter(pcode=instance.code)
if hasChild:
return True
return False
class Meta:
model = Area
fields = "__all__"
read_only_fields = ["id"]
class AreaCreateUpdateSerializer(CustomModelSerializer):
"""
地区管理 创建/更新时的列化器
"""
class Meta:
model = Area
fields = '__all__'
class AreaViewSet(CustomModelViewSet):
"""
地区管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Area.objects.all()
serializer_class = AreaSerializer
extra_filter_class = []
def get_queryset(self):
self.request.query_params._mutable = True
params = self.request.query_params
pcode = params.get('pcode', None)
page = params.get('page', None)
limit = params.get('limit', None)
if page:
del params['page']
if limit:
del params['limit']
if params:
if pcode:
queryset = self.queryset.filter(enable=True, pcode=pcode)
else:
queryset = self.queryset.filter(enable=True)
else:
queryset = self.queryset.filter(enable=True, pcode__isnull=True)
return queryset

View File

@@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
"""
@author: H0nGzA1
@contact: QQ:2505811377
@Remark: 部门管理
"""
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import Dept, RoleMenuButtonPermission
from dvadmin.utils.json_response import DetailResponse, SuccessResponse
from dvadmin.utils.permission import AnonymousUserPermission
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class DeptSerializer(CustomModelSerializer):
"""
部门-序列化器
"""
parent_name = serializers.CharField(read_only=True, source='parent.name')
status_label = serializers.SerializerMethodField()
has_children = serializers.SerializerMethodField()
hasChild = serializers.SerializerMethodField()
def get_hasChild(self, instance):
hasChild = Dept.objects.filter(parent=instance.id)
if hasChild:
return True
return False
def get_status_label(self, obj: Dept):
if obj.status:
return "启用"
return "禁用"
def get_has_children(self, obj: Dept):
return Dept.objects.filter(parent_id=obj.id).count()
class Meta:
model = Dept
fields = '__all__'
read_only_fields = ["id"]
class DeptImportSerializer(CustomModelSerializer):
"""
部门-导入-序列化器
"""
class Meta:
model = Dept
fields = '__all__'
read_only_fields = ["id"]
class DeptCreateUpdateSerializer(CustomModelSerializer):
"""
部门管理 创建/更新时的列化器
"""
def create(self, validated_data):
value = validated_data.get('parent',None)
if value is None:
validated_data['parent'] = self.request.user.dept
instance = super().create(validated_data)
instance.dept_belong_id = instance.id
instance.save()
return instance
class Meta:
model = Dept
fields = '__all__'
class DeptViewSet(CustomModelViewSet):
"""
部门管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Dept.objects.all()
serializer_class = DeptSerializer
create_serializer_class = DeptCreateUpdateSerializer
update_serializer_class = DeptCreateUpdateSerializer
filter_fields = ['name', 'id', 'parent']
search_fields = []
# extra_filter_class = []
import_serializer_class = DeptImportSerializer
import_field_dict = {
"name": "部门名称",
"key": "部门标识",
}
def list(self, request, *args, **kwargs):
# 如果懒加载,则只返回父级
request.query_params._mutable = True
params = request.query_params
parent = params.get('parent', None)
page = params.get('page', None)
limit = params.get('limit', None)
if page:
del params['page']
if limit:
del params['limit']
if params:
if parent:
queryset = self.queryset.filter(status=True, parent=parent)
else:
queryset = self.queryset.filter(status=True)
else:
queryset = self.queryset.filter(status=True, parent__isnull=True)
queryset = self.filter_queryset(queryset)
serializer = DeptSerializer(queryset, many=True, request=request)
data = serializer.data
return SuccessResponse(data=data)
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated], extra_filter_class=[])
def dept_lazy_tree(self, request, *args, **kwargs):
parent = self.request.query_params.get('parent')
is_superuser = request.user.is_superuser
if is_superuser:
queryset = Dept.objects.values('id', 'name', 'parent')
else:
role_ids = request.user.role.values_list('id',flat=True)
data_range = RoleMenuButtonPermission.objects.filter(role__in=role_ids).values_list('data_range', flat=True)
user_dept_id = request.user.dept.id
dept_list = [user_dept_id]
data_range_list = list(set(data_range))
for item in data_range_list:
if item in [0,2]:
dept_list = [user_dept_id]
elif item == 1:
dept_list = Dept.recursion_dept_info(dept_id=user_dept_id)
elif item == 3:
dept_list = Dept.objects.values_list('id',flat=True)
elif item == 4:
dept_list = request.user.role.values_list('dept',flat=True)
else:
dept_list = []
queryset = Dept.objects.filter(id__in=dept_list).values('id', 'name', 'parent')
return DetailResponse(data=queryset, msg="获取成功")
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated],extra_filter_class=[])
def all_dept(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
data = queryset.filter(status=True).order_by('sort').values('name', 'id', 'parent')
return DetailResponse(data=data, msg="获取成功")

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 字典管理
"""
from rest_framework import serializers
from rest_framework.views import APIView
from application import dispatch
from dvadmin.system.models import Dictionary
from dvadmin.utils.json_response import SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class DictionarySerializer(CustomModelSerializer):
"""
字典-序列化器
"""
class Meta:
model = Dictionary
fields = "__all__"
read_only_fields = ["id"]
class DictionaryCreateUpdateSerializer(CustomModelSerializer):
"""
字典管理 创建/更新时的列化器
"""
value = serializers.CharField(max_length=100)
def validate_value(self, value):
"""
在父级的字典编号验证重复性
"""
initial_data = self.initial_data
parent = initial_data.get('parent',None)
if parent is None:
unique = Dictionary.objects.filter(value=value).exists()
if unique:
raise serializers.ValidationError("字典编号不能重复")
return value
class Meta:
model = Dictionary
fields = '__all__'
class DictionaryViewSet(CustomModelViewSet):
"""
字典管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Dictionary.objects.all()
serializer_class = DictionarySerializer
create_serializer_class = DictionaryCreateUpdateSerializer
extra_filter_class = []
search_fields = ['label']
def get_queryset(self):
if self.action =='list':
params = self.request.query_params
parent = params.get('parent', None)
if params:
if parent:
queryset = self.queryset.filter(parent=parent)
else:
queryset = self.queryset.filter(parent__isnull=True)
else:
queryset = self.queryset.filter(parent__isnull=True)
return queryset
else:
return self.queryset
class InitDictionaryViewSet(APIView):
"""
获取初始化配置
"""
authentication_classes = []
permission_classes = []
queryset = Dictionary.objects.all()
def get(self, request):
dictionary_key = self.request.query_params.get('dictionary_key')
if dictionary_key:
if dictionary_key == 'all':
data = [ele for ele in dispatch.get_dictionary_config().values()]
if not data:
dispatch.refresh_dictionary()
data = [ele for ele in dispatch.get_dictionary_config().values()]
else:
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
'color')
return SuccessResponse(data=data, msg="获取成功")
return SuccessResponse(data=[], msg="获取成功")

View File

@@ -0,0 +1,79 @@
import hashlib
import mimetypes
from rest_framework import serializers
from rest_framework.decorators import action
from application import dispatch
from dvadmin.system.models import FileList
from dvadmin.utils.json_response import DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class FileSerializer(CustomModelSerializer):
url = serializers.SerializerMethodField(read_only=True)
def get_url(self, instance):
# return 'media/' + str(instance.url)
return instance.file_url or (f'media/{str(instance.url)}')
class Meta:
model = FileList
fields = "__all__"
def create(self, validated_data):
file_engine = dispatch.get_system_config_values("fileStorageConfig.file_engine") or 'local'
file_backup = dispatch.get_system_config_values("fileStorageConfig.file_backup")
file = self.initial_data.get('file')
file_size = file.size
validated_data['name'] = str(file)
validated_data['size'] = file_size
md5 = hashlib.md5()
for chunk in file.chunks():
md5.update(chunk)
validated_data['md5sum'] = md5.hexdigest()
validated_data['engine'] = file_engine
validated_data['mime_type'] = file.content_type
if file_backup:
validated_data['url'] = file
if file_engine == 'oss':
from dvadmin_cloud_storage.views.aliyun import ali_oss_upload
file_path = ali_oss_upload(file)
if file_path:
validated_data['file_url'] = file_path
else:
raise ValueError("上传失败")
elif file_engine == 'cos':
from dvadmin_cloud_storage.views.tencent import tencent_cos_upload
file_path = tencent_cos_upload(file)
if file_path:
validated_data['file_url'] = file_path
else:
raise ValueError("上传失败")
else:
validated_data['url'] = file
# 审计字段
try:
request_user = self.request.user
validated_data['dept_belong_id'] = request_user.dept.id
validated_data['creator'] = request_user.id
validated_data['modifier'] = request_user.id
except:
pass
return super().create(validated_data)
class FileViewSet(CustomModelViewSet):
"""
文件管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = FileList.objects.all()
serializer_class = FileSerializer
filter_fields = ['name', ]
permission_classes = []

View File

@@ -0,0 +1,251 @@
import base64
import hashlib
from datetime import datetime, timedelta
from captcha.views import CaptchaStore, captcha_image
from django.contrib import auth
from django.contrib.auth import login
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from application import dispatch
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.request_util import save_login_log
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomValidationError
class CaptchaView(APIView):
authentication_classes = []
permission_classes = []
@swagger_auto_schema(
responses={"200": openapi.Response("获取成功")},
security=[],
operation_id="captcha-get",
operation_description="验证码获取",
)
def get(self, request):
data = {}
if dispatch.get_system_config_values("base.captcha_state"):
hashkey = CaptchaStore.generate_key()
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
imgage = captcha_image(request, hashkey)
# 将图片转换为base64
image_base = base64.b64encode(imgage.content)
data = {
"key": id,
"image_base": "data:image/png;base64," + image_base.decode("utf-8"),
}
return DetailResponse(data=data)
class LoginSerializer(TokenObtainPairSerializer):
"""
登录的序列化器:
重写djangorestframework-simplejwt的序列化器
"""
captcha = serializers.CharField(
max_length=6, required=False, allow_null=True, allow_blank=True
)
class Meta:
model = Users
fields = "__all__"
read_only_fields = ["id"]
default_error_messages = {"no_active_account": _("账号/密码错误")}
def validate(self, attrs):
captcha = self.initial_data.get("captcha", None)
if dispatch.get_system_config_values("base.captcha_state"):
if captcha is None:
raise CustomValidationError("验证码不能为空")
self.image_code = CaptchaStore.objects.filter(
id=self.initial_data["captchaKey"]
).first()
five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
if self.image_code and five_minute_ago > self.image_code.expiration:
self.image_code and self.image_code.delete()
raise CustomValidationError("验证码过期")
else:
if self.image_code and (
self.image_code.response == captcha
or self.image_code.challenge == captcha
):
self.image_code and self.image_code.delete()
else:
self.image_code and self.image_code.delete()
raise CustomValidationError("图片验证码错误")
user = Users.objects.get(username=attrs['username'])
if not user.is_active:
raise CustomValidationError("账号被锁定")
data = super().validate(attrs)
data["name"] = self.user.name
data["userId"] = self.user.id
data["avatar"] = self.user.avatar
data['user_type'] = self.user.user_type
dept = getattr(self.user, 'dept', None)
if dept:
data['dept_info'] = {
'dept_id': dept.id,
'dept_name': dept.name,
}
role = getattr(self.user, 'role', None)
if role:
data['role_info'] = role.values('id', 'name', 'key')
request = self.context.get("request")
request.user = self.user
# 记录登录日志
save_login_log(request=request)
return {"code": 2000, "msg": "请求成功", "data": data}
class LoginView(TokenObtainPairView):
"""
登录接口
"""
serializer_class = LoginSerializer
permission_classes = []
# def post(self, request, *args, **kwargs):
# # username可能携带的不止是用户名可能还是用户的其它唯一标识 手机号 邮箱
# username = request.data.get('username',None)
# if username is None:
# return ErrorResponse(msg="参数错误")
# password = request.data.get('password',None)
# if password is None:
# return ErrorResponse(msg="参数错误")
# captcha = request.data.get('captcha',None)
# if captcha is None:
# return ErrorResponse(msg="参数错误")
# captchaKey = request.data.get('captchaKey',None)
# if captchaKey is None:
# return ErrorResponse(msg="参数错误")
# if dispatch.get_system_config_values("base.captcha_state"):
# if captcha is None:
# raise CustomValidationError("验证码不能为空")
# self.image_code = CaptchaStore.objects.filter(
# id=captchaKey
# ).first()
# five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
# if self.image_code and five_minute_ago > self.image_code.expiration:
# self.image_code and self.image_code.delete()
# raise CustomValidationError("验证码过期")
# else:
# if self.image_code and (
# self.image_code.response == captcha
# or self.image_code.challenge == captcha
# ):
# self.image_code and self.image_code.delete()
# else:
# self.image_code and self.image_code.delete()
# raise CustomValidationError("图片验证码错误")
# try:
# # 手动通过 user 签发 jwt-token
# user = Users.objects.get(username=username)
# except:
# return DetailResponse(msg='该账号未注册')
# # 获得用户后校验密码并签发token
# print(make_password(password),user.password)
# if check_password(make_password(password),user.password):
# return DetailResponse(msg='密码错误')
# result = {
# "name":user.name,
# "userId":user.id,
# "avatar":user.avatar,
# }
# dept = getattr(user, 'dept', None)
# if dept:
# result['dept_info'] = {
# 'dept_id': dept.id,
# 'dept_name': dept.name,
# 'dept_key': dept.key
# }
# role = getattr(user, 'role', None)
# if role:
# result['role_info'] = role.values('id', 'name', 'key')
# refresh = LoginSerializer.get_token(user)
# result["refresh"] = str(refresh)
# result["access"] = str(refresh.access_token)
# # 记录登录日志
# request.user = user
# save_login_log(request=request)
# return DetailResponse(data=result,msg="获取成功")
class LoginTokenSerializer(TokenObtainPairSerializer):
"""
登录的序列化器:
"""
class Meta:
model = Users
fields = "__all__"
read_only_fields = ["id"]
default_error_messages = {"no_active_account": _("账号/密码不正确")}
def validate(self, attrs):
if not getattr(settings, "LOGIN_NO_CAPTCHA_AUTH", False):
return {"code": 4000, "msg": "该接口暂未开通!", "data": None}
data = super().validate(attrs)
data["name"] = self.user.name
data["userId"] = self.user.id
return {"code": 2000, "msg": "请求成功", "data": data}
class LoginTokenView(TokenObtainPairView):
"""
登录获取token接口
"""
serializer_class = LoginTokenSerializer
permission_classes = []
class LogoutView(APIView):
def post(self, request):
return DetailResponse(msg="注销成功")
class ApiLoginSerializer(CustomModelSerializer):
"""接口文档登录-序列化器"""
username = serializers.CharField()
password = serializers.CharField()
class Meta:
model = Users
fields = ["username", "password"]
class ApiLogin(APIView):
"""接口文档的登录接口"""
serializer_class = ApiLoginSerializer
authentication_classes = []
permission_classes = []
def post(self, request):
username = request.data.get("username")
password = request.data.get("password")
user_obj = auth.authenticate(
request,
username=username,
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
)
if user_obj:
login(request, user_obj)
return redirect("/")
else:
return ErrorResponse(msg="账号/密码错误")

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 按钮权限管理
"""
from dvadmin.system.models import LoginLog
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class LoginLogSerializer(CustomModelSerializer):
"""
登录日志权限-序列化器
"""
class Meta:
model = LoginLog
fields = "__all__"
read_only_fields = ["id"]
class LoginLogViewSet(CustomModelViewSet):
"""
登录日志接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = LoginLog.objects.all()
serializer_class = LoginLogSerializer
extra_filter_class = []

View File

@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/1 001 22:38
@Remark: 菜单模块
"""
from rest_framework import serializers
from rest_framework.decorators import action
from dvadmin.system.models import Menu, MenuButton, RoleMenuPermission
from dvadmin.utils.json_response import SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class MenuSerializer(CustomModelSerializer):
"""
菜单表的简单序列化器
"""
menuPermission = serializers.SerializerMethodField(read_only=True)
hasChild = serializers.SerializerMethodField()
def get_menuPermission(self, instance):
queryset = instance.menuPermission.order_by('-name').values_list('name', flat=True)
if queryset:
return queryset
else:
return None
def get_hasChild(self, instance):
hasChild = Menu.objects.filter(parent=instance.id)
if hasChild:
return True
return False
class Meta:
model = Menu
fields = "__all__"
read_only_fields = ["id"]
class MenuCreateSerializer(CustomModelSerializer):
"""
菜单表的创建序列化器
"""
name = serializers.CharField(required=False)
class Meta:
model = Menu
fields = "__all__"
read_only_fields = ["id"]
class WebRouterSerializer(CustomModelSerializer):
"""
前端菜单路由的简单序列化器
"""
path = serializers.CharField(source="web_path")
title = serializers.CharField(source="name")
class Meta:
model = Menu
fields = (
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
'component_name', 'cache', 'visible', 'status')
read_only_fields = ["id"]
class MenuViewSet(CustomModelViewSet):
"""
菜单管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Menu.objects.all()
serializer_class = MenuSerializer
create_serializer_class = MenuCreateSerializer
update_serializer_class = MenuCreateSerializer
search_fields = ['name', 'status']
filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog']
# extra_filter_class = []
@action(methods=['GET'], detail=False, permission_classes=[])
def web_router(self, request):
"""用于前端获取当前角色的路由"""
user = request.user
is_admin = user.role.values_list('admin', flat=True)
if user.is_superuser or True in is_admin:
queryset = self.queryset.filter(status=1)
else:
role_list = user.role.values_list('id', flat=True)
menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id',flat=True)
print("role_list", role_list)
print("menu_list",menu_list)
queryset = Menu.objects.filter(id__in=menu_list)
print(queryset)
serializer = WebRouterSerializer(queryset, many=True, request=request)
data = serializer.data
return SuccessResponse(data=data, total=len(data), msg="获取成功")
@action(methods=['GET'], detail=False, permission_classes=[])
def get_all_menu(self, request):
"""用于菜单管理获取所有的菜单"""
user = request.user
queryset = self.queryset.all()
if not user.is_superuser:
role_list = user.role.values_list('id', flat=True)
menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id')
queryset = Menu.objects.filter(id__in=menu_list)
serializer = WebRouterSerializer(queryset, many=True, request=request)
data = serializer.data
return SuccessResponse(data=data, total=len(data), msg="获取成功")
@action(methods=['POST'], detail=False, permission_classes=[])
def drag_menu(self, request):
"""前端拖拽菜单之后重写parent"""
menu_id = request.data['menu_id']
parent_id = request.data['parent_id']
menu = Menu.objects.get(id=menu_id)
menu.parent_id = parent_id
menu.save()
return SuccessResponse(data=[], msg="拖拽菜单成功")
def list(self, request):
"""懒加载"""
request.query_params._mutable = True
params = request.query_params
parent = params.get('parent', None)
page = params.get('page', None)
limit = params.get('limit', None)
if page:
del params['page']
if limit:
del params['limit']
if params:
if parent:
queryset = self.queryset.filter(parent=parent)
else:
queryset = self.queryset.filter()
else:
queryset = self.queryset.filter(parent__isnull=True)
queryset = self.filter_queryset(queryset)
serializer = MenuSerializer(queryset, many=True, request=request)
data = serializer.data
return SuccessResponse(data=data)

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 菜单按钮管理
"""
from django.db.models import F
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import MenuButton, RoleMenuButtonPermission
from dvadmin.utils.json_response import DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class MenuButtonSerializer(CustomModelSerializer):
"""
菜单按钮-序列化器
"""
class Meta:
model = MenuButton
fields = ['id', 'name', 'value', 'api', 'method','menu']
read_only_fields = ["id"]
class MenuButtonCreateUpdateSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = MenuButton
fields = "__all__"
read_only_fields = ["id"]
class MenuButtonViewSet(CustomModelViewSet):
"""
菜单按钮接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = MenuButton.objects.all()
serializer_class = MenuButtonSerializer
create_serializer_class = MenuButtonCreateUpdateSerializer
update_serializer_class = MenuButtonCreateUpdateSerializer
extra_filter_class = []
@action(methods=['get'],detail=False,permission_classes=[IsAuthenticated])
def menu_button_all_permission(self,request):
"""
获取所有的按钮权限
:param request:
:return:
"""
is_superuser = request.user.is_superuser
is_admin = request.user.role.values_list('admin', flat=True)
if is_superuser or True in is_admin:
queryset = MenuButton.objects.values_list('value',flat=True)
else:
role_id = request.user.role.values_list('id', flat=True)
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_id).values_list('menu_button__value',flat=True).distinct()
return DetailResponse(data=queryset)

View File

@@ -0,0 +1,218 @@
# -*- coding: utf-8 -*-
import json
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django_restql.fields import DynamicSerializerMethodField
from rest_framework import serializers
from rest_framework.decorators import action, permission_classes
from rest_framework.permissions import IsAuthenticated, AllowAny
from dvadmin.system.models import MessageCenter, Users, MessageCenterTargetUser
from dvadmin.utils.json_response import SuccessResponse, DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class MessageCenterSerializer(CustomModelSerializer):
"""
消息中心-序列化器
"""
role_info = DynamicSerializerMethodField()
user_info = DynamicSerializerMethodField()
dept_info = DynamicSerializerMethodField()
is_read = serializers.BooleanField(read_only=True, source='target_user__is_read')
def get_role_info(self, instance, parsed_query):
roles = instance.target_role.all()
# You can do what ever you want in here
# `parsed_query` param is passed to BookSerializer to allow further querying
from dvadmin.system.views.role import RoleSerializer
serializer = RoleSerializer(
roles,
many=True,
parsed_query=parsed_query
)
return serializer.data
def get_user_info(self, instance, parsed_query):
users = instance.target_user.all()
# You can do what ever you want in here
# `parsed_query` param is passed to BookSerializer to allow further querying
from dvadmin.system.views.user import UserSerializer
serializer = UserSerializer(
users,
many=True,
parsed_query=parsed_query
)
return serializer.data
def get_dept_info(self, instance, parsed_query):
dept = instance.target_dept.all()
# You can do what ever you want in here
# `parsed_query` param is passed to BookSerializer to allow further querying
from dvadmin.system.views.dept import DeptSerializer
serializer = DeptSerializer(
dept,
many=True,
parsed_query=parsed_query
)
return serializer.data
class Meta:
model = MessageCenter
fields = "__all__"
read_only_fields = ["id"]
class MessageCenterTargetUserSerializer(CustomModelSerializer):
"""
目标用户序列化器-序列化器
"""
class Meta:
model = MessageCenterTargetUser
fields = "__all__"
read_only_fields = ["id"]
class MessageCenterTargetUserListSerializer(CustomModelSerializer):
"""
目标用户序列化器-序列化器
"""
is_read = serializers.SerializerMethodField()
def get_is_read(self, instance):
user_id = self.request.user.id
message_center_id = instance.id
queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id, users_id=user_id).first()
if queryset:
return queryset.is_read
return False
class Meta:
model = MessageCenter
fields = "__all__"
read_only_fields = ["id"]
def websocket_push(user_id, message):
"""
主动推送消息
"""
username = "user_" + str(user_id)
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
username,
{
"type": "push.message",
"json": message
}
)
class MessageCenterCreateSerializer(CustomModelSerializer):
"""
消息中心-新增-序列化器
"""
def save(self, **kwargs):
data = super().save(**kwargs)
initial_data = self.initial_data
target_type = initial_data.get('target_type')
# 在保存之前,根据目标类型,把目标用户查询出来并保存
users = initial_data.get('target_user', [])
if target_type in [1]: # 按角色
target_role = initial_data.get('target_role', [])
users = Users.objects.filter(role__id__in=target_role).values_list('id', flat=True)
if target_type in [2]: # 按部门
target_dept = initial_data.get('target_dept', [])
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
if target_type in [3]: # 系统通知
users = Users.objects.values_list('id', flat=True)
targetuser_data = []
for user in users:
targetuser_data.append({
"messagecenter": data.id,
"users": user
})
targetuser_instance = MessageCenterTargetUserSerializer(data=targetuser_data, many=True, request=self.request)
targetuser_instance.is_valid(raise_exception=True)
targetuser_instance.save()
for user in users:
unread_count = MessageCenterTargetUser.objects.filter(users__id=user, is_read=False).count()
websocket_push(user, message={"sender": 'system', "contentType": 'SYSTEM',
"content": '您有一条新消息~', "unread": unread_count})
return data
class Meta:
model = MessageCenter
fields = "__all__"
read_only_fields = ["id"]
class MessageCenterViewSet(CustomModelViewSet):
"""
消息中心接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = MessageCenter.objects.order_by('create_datetime')
serializer_class = MessageCenterSerializer
create_serializer_class = MessageCenterCreateSerializer
extra_filter_backends = []
def get_queryset(self):
if self.action == 'list':
return MessageCenter.objects.filter(creator=self.request.user.id).all()
return MessageCenter.objects.all()
def retrieve(self, request, *args, **kwargs):
"""
重写查看
"""
pk = kwargs.get('pk')
user_id = self.request.user.id
queryset = MessageCenterTargetUser.objects.filter(users__id=user_id, messagecenter__id=pk).first()
if queryset:
queryset.is_read = True
queryset.save()
instance = self.get_object()
serializer = self.get_serializer(instance)
# 主动推送消息
unread_count = MessageCenterTargetUser.objects.filter(users__id=user_id, is_read=False).count()
websocket_push(user_id, message={"sender": 'system', "contentType": 'TEXT',
"content": '您查看了一条消息~', "unread": unread_count})
return DetailResponse(data=serializer.data, msg="获取成功")
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def get_self_receive(self, request):
"""
获取接收到的消息
"""
self_user_id = self.request.user.id
# queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('-create_datetime')
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
# queryset = self.filter_queryset(queryset)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = MessageCenterTargetUserListSerializer(page, many=True, request=request)
return self.get_paginated_response(serializer.data)
serializer = MessageCenterTargetUserListSerializer(queryset, many=True, request=request)
return SuccessResponse(data=serializer.data, msg="获取成功")
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def get_newest_msg(self, request):
"""
获取最新的一条消息
"""
self_user_id = self.request.user.id
queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('create_datetime').last()
data = None
if queryset:
serializer = MessageCenterTargetUserListSerializer(queryset.messagecenter, many=False, request=request)
data = serializer.data
return DetailResponse(data=data, msg="获取成功")

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
@author: 李强
@contact: QQ:1206709430
@Created on: 2021/6/8 003 0:30
@Remark: 操作日志管理
"""
from dvadmin.system.models import OperationLog
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class OperationLogSerializer(CustomModelSerializer):
"""
日志-序列化器
"""
class Meta:
model = OperationLog
fields = "__all__"
read_only_fields = ["id"]
class OperationLogCreateUpdateSerializer(CustomModelSerializer):
"""
操作日志 创建/更新时的列化器
"""
class Meta:
model = OperationLog
fields = '__all__'
class OperationLogViewSet(CustomModelViewSet):
"""
操作日志接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = OperationLog.objects.order_by('-create_datetime')
serializer_class = OperationLogSerializer
# permission_classes = []

View File

@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 角色管理
"""
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import Role, Menu, MenuButton, Dept
from dvadmin.system.views.dept import DeptSerializer
from dvadmin.system.views.menu import MenuSerializer
from dvadmin.system.views.menu_button import MenuButtonSerializer
from dvadmin.utils.crud_mixin import FastCrudMixin
from dvadmin.utils.json_response import SuccessResponse, DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomUniqueValidator
from dvadmin.utils.viewset import CustomModelViewSet
class RoleSerializer(CustomModelSerializer):
"""
角色-序列化器
"""
class Meta:
model = Role
fields = "__all__"
read_only_fields = ["id"]
class RoleCreateUpdateSerializer(CustomModelSerializer):
"""
角色管理 创建/更新时的列化器
"""
menu = MenuSerializer(many=True, read_only=True)
dept = DeptSerializer(many=True, read_only=True)
permission = MenuButtonSerializer(many=True, read_only=True)
key = serializers.CharField(max_length=50,
validators=[CustomUniqueValidator(queryset=Role.objects.all(), message="权限字符必须唯一")])
name = serializers.CharField(max_length=50, validators=[CustomUniqueValidator(queryset=Role.objects.all())])
def validate(self, attrs: dict):
return super().validate(attrs)
def save(self, **kwargs):
is_superuser = self.request.user.is_superuser
if not is_superuser:
self.validated_data.pop('admin')
data = super().save(**kwargs)
return data
class Meta:
model = Role
fields = '__all__'
class MenuPermissonSerializer(CustomModelSerializer):
"""
菜单的按钮权限
"""
menuPermission = serializers.SerializerMethodField()
def get_menuPermission(self, instance):
is_superuser = self.request.user.is_superuser
if is_superuser:
queryset = MenuButton.objects.filter(menu__id=instance.id)
else:
menu_permission_id_list = self.request.user.role.values_list('permission',flat=True)
queryset = MenuButton.objects.filter(id__in=menu_permission_id_list,menu__id=instance.id)
serializer = MenuButtonSerializer(queryset,many=True, read_only=True)
return serializer.data
class Meta:
model = Menu
fields = ['id', 'parent', 'name', 'menuPermission']
class RoleViewSet(CustomModelViewSet,FastCrudMixin):
"""
角色管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Role.objects.all()
serializer_class = RoleSerializer
create_serializer_class = RoleCreateUpdateSerializer
update_serializer_class = RoleCreateUpdateSerializer
search_fields = ['name', 'key']

View File

@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
from django.db.models import F
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import RoleMenuPermission, Menu, MenuButton
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class RoleMenuPermissionSerializer(CustomModelSerializer):
"""
菜单按钮-序列化器
"""
class Meta:
model = RoleMenuPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuPermissionInitSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = RoleMenuPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuPermissionCreateUpdateSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = RoleMenuPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuPermissionViewSet(CustomModelViewSet):
"""
菜单按钮接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = RoleMenuPermission.objects.all()
serializer_class = RoleMenuPermissionSerializer
create_serializer_class = RoleMenuPermissionCreateUpdateSerializer
update_serializer_class = RoleMenuPermissionCreateUpdateSerializer
extra_filter_class = []
@action(methods=['post'],detail=False)
def save_auth(self,request):
"""
保存页面菜单授权
:param request:
:return:
"""
body = request.data
role_id = body.get('role',None)
if role_id is None:
return ErrorResponse(msg="未获取到角色参数")
menu_list = body.get('menu',None)
if menu_list is None:
return ErrorResponse(msg="未获取到菜单参数")
obj_list = RoleMenuPermission.objects.filter(role__id=role_id).values_list('menu__id',flat=True)
old_set = set(obj_list)
new_set = set(menu_list)
#need_update = old_set.intersection(new_set) # 需要更新的
need_del = old_set.difference(new_set) # 需要删除的
need_add = new_set.difference(old_set) # 需要新增的
RoleMenuPermission.objects.filter(role__id=role_id,menu__in=list(need_del)).delete()
data = [{"role": role_id, "menu": item} for item in list(need_add)]
serializer = RoleMenuPermissionSerializer(data=data,many=True,request=request)
if serializer.is_valid(raise_exception=True):
serializer.save()
return DetailResponse(msg="保存成功",data=serializer.data)

View File

@@ -0,0 +1,280 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 菜单按钮管理
"""
from django.db.models import F, Subquery, OuterRef, Exists
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
"""
菜单按钮-序列化器
"""
class Meta:
model = RoleMenuButtonPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuButtonPermissionInitSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = RoleMenuButtonPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
menu_button__name = serializers.CharField(source='menu_button.name', read_only=True)
menu_button__value= serializers.CharField(source='menu_button.value', read_only=True)
class Meta:
model = RoleMenuButtonPermission
fields = "__all__"
read_only_fields = ["id"]
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
"""
菜单按钮接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = RoleMenuButtonPermission.objects.all()
serializer_class = RoleMenuButtonPermissionSerializer
create_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
update_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
extra_filter_class = []
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def role_get_menu(self, request):
"""根据当前用户的角色返回角色拥有的菜单"""
data = []
is_superuser = request.user.is_superuser
is_admin = request.user.role.values_list('admin', flat=True)
if is_superuser or True in is_admin:
queryset = Menu.objects.filter(status=1).values('name','parent','is_catalog',menu_id=F('id'))
for item in queryset:
btn_name = MenuButton.objects.filter(menu=item['menu_id']).values_list(
'name', flat=True)
data.append({'menu_id': item['menu_id'], 'name': item['name'], 'parent': item['parent'],
'permission': ','.join(btn_name), 'is_catalog': item['is_catalog']})
else:
role_id = request.user.role.values_list('id',flat=True)
queryset = RoleMenuPermission.objects.filter(role__in=role_id).values('menu_id',name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog')).distinct()
for item in queryset:
btn_name = RoleMenuButtonPermission.objects.filter(menu_button__menu=item['menu_id']).values_list('menu_button__name',flat=True)
data.append({'menu_id':item['menu_id'], 'name':item['name'], 'parent':item['parent'],'permission':','.join(btn_name),'is_catalog':item['is_catalog']})
return DetailResponse(data=data)
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def role_menu_get_button(self,request):
"""
当前用户角色和菜单获取可下拉选项的按钮:角色授权页面使用
:param request:
:return:
"""
if params := request.query_params:
if menu_id := params.get('menu', None):
is_superuser = request.user.is_superuser
is_admin = request.user.role.values_list('admin', flat=True)
if is_superuser or True in is_admin:
queryset = MenuButton.objects.filter(menu=menu_id).values('id', 'name')
else:
role_list = request.user.role.values_list('id',flat=True)
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__menu=menu_id).values(
btn_id=F('menu_button__id'),
name=F('menu_button__name')
)
return DetailResponse(data=queryset)
return ErrorResponse(msg="参数错误")
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def data_scope(self, request):
"""
获取数据权限范围:角色授权页面使用
:param request:
:return:
"""
is_superuser = request.user.is_superuser
if is_superuser:
data = [
{
"value": 0,
"label": '仅本人数据权限'
},
{
"value": 1,
"label": '本部门及以下数据权限'
},
{
"value": 2,
"label": '本部门数据权限'
},
{
"value": 3,
"label": '全部数据权限'
},
{
"value": 4,
"label": '自定义数据权限'
}
]
return DetailResponse(data=data)
else:
data = []
role_list = request.user.role.values_list('id',flat=True)
if params := request.query_params:
if menu_button_id := params.get('menu_button', None):
role_queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__id=menu_button_id).values_list('data_range',flat=True)
data_range_list = list(set(role_queryset))
for item in data_range_list:
if item == 0:
data = [{
"value": 0,
"label": '仅本人数据权限'
}]
elif item == 1:
data = [{
"value": 0,
"label": '仅本人数据权限'
}, {
"value": 1,
"label": '本部门及以下数据权限'
},
{
"value": 2,
"label": '本部门数据权限'
}]
elif item == 2:
data = [{
"value": 0,
"label": '仅本人数据权限'
},
{
"value": 2,
"label": '本部门数据权限'
}]
elif item == 3:
data = [{
"value": 0,
"label": '仅本人数据权限'
},
{
"value": 3,
"label": '全部数据权限'
}, ]
elif item == 4:
data = [{
"value": 0,
"label": '仅本人数据权限'
},
{
"value": 4,
"label": '自定义数据权限'
}]
else:
data = []
return DetailResponse(data=data)
return ErrorResponse(msg="参数错误")
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
def role_to_dept_all(self, request):
"""
当前用户角色下所能授权的部门:角色授权页面使用
:param request:
:return:
"""
params = request.query_params
is_superuser = request.user.is_superuser
is_admin = request.user.role.values_list('admin', flat=True)
if is_superuser or True in is_admin:
queryset = Dept.objects.values('id','name','parent')
else:
if not params:
return ErrorResponse(msg="参数错误")
menu_button = params.get('menu_button')
if menu_button is None:
return ErrorResponse(msg="参数错误")
role_list = request.user.role.values_list('id', flat=True)
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button=None).values(
dept_id=F('dept__id'),
name=F('dept__name'),
parent=F('dept__parent')
)
return DetailResponse(data=queryset)
@action(methods=['get'],detail=False,permission_classes=[IsAuthenticated])
def menu_to_button(self,request):
"""
根据所选择菜单获取已配置的按钮/接口权限:角色授权页面使用
:param request:
:return:
"""
params = request.query_params
menu_id = params.get('menu', None)
if menu_id is None:
return ErrorResponse(msg="未获取到参数")
is_superuser = request.user.is_superuser
is_admin = request.user.role.values_list('admin', flat=True)
if is_superuser or True in is_admin:
queryset = RoleMenuButtonPermission.objects.filter(menu_button__menu=menu_id).values(
'id',
'data_range',
'menu_button',
'menu_button__name',
'menu_button__value'
)
return DetailResponse(data=queryset)
else:
if params:
role_id = params.get('role', None)
if role_id is None:
return ErrorResponse(msg="未获取到参数")
queryset = RoleMenuButtonPermission.objects.filter(role=role_id,menu_button__menu=menu_id).values(
'id',
'data_range',
'menu_button',
'menu_button__name',
'menu_button__value'
)
return DetailResponse(data=queryset)
return ErrorResponse(msg="未获取到参数")
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
def role_to_menu(self, request):
"""
获取角色对应的按钮权限
:param request:
:return:
"""
params = request.query_params
role_id = params.get('role', None)
if role_id is None:
return ErrorResponse(msg="未获取到参数")
queryset = RoleMenuPermission.objects.filter(role_id=role_id).values_list('menu_id',flat=True).distinct()
return DetailResponse(data=queryset)

View File

@@ -0,0 +1,234 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2022/1/21 003 0:30
@Remark: 系统配置
"""
import django_filters
from django.db.models import Q
from django_filters.rest_framework import BooleanFilter
from rest_framework import serializers
from rest_framework.views import APIView
from application import dispatch
from dvadmin.system.models import SystemConfig
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
from dvadmin.utils.models import get_all_models_objects
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomValidationError
from dvadmin.utils.viewset import CustomModelViewSet
class SystemConfigCreateSerializer(CustomModelSerializer):
"""
系统配置-新增时使用-序列化器
"""
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
class Meta:
model = SystemConfig
fields = "__all__"
read_only_fields = ["id"]
def validate_key(self, value):
"""
验证key是否允许重复
parent为空时不允许重复,反之允许
"""
instance = SystemConfig.objects.filter(key=value, parent__isnull=True).exists()
if instance:
raise CustomValidationError('已存在相同变量名')
return value
class SystemConfigSerializer(CustomModelSerializer):
"""
系统配置-序列化器
"""
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
class Meta:
model = SystemConfig
fields = "__all__"
read_only_fields = ["id"]
class SystemConfigChinldernSerializer(CustomModelSerializer):
"""
系统配置子级-序列化器
"""
children = serializers.SerializerMethodField()
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
def get_children(self, instance):
queryset = SystemConfig.objects.filter(parent=instance)
serializer = SystemConfigSerializer(queryset, many=True)
return serializer.data
class Meta:
model = SystemConfig
fields = "__all__"
read_only_fields = ["id"]
class SystemConfigListSerializer(CustomModelSerializer):
"""
系统配置下模块的保存-序列化器
"""
def update(self, instance, validated_data):
instance_mapping = {obj.id: obj for obj in instance}
data_mapping = {item['id']: item for item in validated_data}
for obj_id, data in data_mapping.items():
instance_obj = instance_mapping.get(obj_id, None)
if instance_obj is None:
return SystemConfig.objects.create(**data)
else:
return instance_obj.objects.update(**data)
class Meta:
model = SystemConfig
fields = "__all__"
read_only_fields = ["id"]
class SystemConfigSaveSerializer(serializers.Serializer):
class Meta:
read_only_fields = ["id"]
list_serializer_class = SystemConfigListSerializer
class SystemConfigFilter(django_filters.rest_framework.FilterSet):
"""
过滤器
"""
parent__isnull = BooleanFilter(field_name='parent', lookup_expr="isnull")
class Meta:
model = SystemConfig
fields = ['id', 'parent', 'status', 'parent__isnull']
class SystemConfigViewSet(CustomModelViewSet):
"""
系统配置接口
"""
queryset = SystemConfig.objects.order_by('sort', 'create_datetime')
serializer_class = SystemConfigChinldernSerializer
create_serializer_class = SystemConfigCreateSerializer
retrieve_serializer_class = SystemConfigChinldernSerializer
# filter_fields = ['id','parent']
filter_class = SystemConfigFilter
def save_content(self, request):
body = request.data
data_mapping = {item['id']: item for item in body}
for obj_id, data in data_mapping.items():
instance_obj = SystemConfig.objects.filter(id=obj_id).first()
if instance_obj is None:
# return SystemConfig.objects.create(**data)
serializer = SystemConfigCreateSerializer(data=data)
else:
serializer = SystemConfigCreateSerializer(instance_obj, data=data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return DetailResponse(msg="保存成功")
def get_association_table(self, request):
"""
获取所有的model及字段信息
"""
res = [ele.get('table') for ele in get_all_models_objects().values()]
return DetailResponse(msg="获取成功", data=res)
def get_table_data(self, request, pk):
"""
动态获取关联表的数据
"""
instance = SystemConfig.objects.filter(id=pk).first()
if instance is None:
return ErrorResponse(msg="查询出错了~")
setting = instance.setting
if setting is None:
return ErrorResponse(msg="查询出错了~")
table = setting.get('table') # 获取model名
model = get_all_models_objects(table).get("object", {})
# 自己判断一下不存在
queryset = model.objects.values()
body = request.query_params
search_value = body.get('search', None)
if search_value:
search_fields = setting.get('searchField')
filters = Q()
filters.connector = 'OR'
for item in search_fields:
filed = '{0}__icontains'.format(item.get('field'))
filters.children.append((filed, search_value))
queryset = model.objects.filter(filters).values()
page = self.paginate_queryset(queryset)
if page is not None:
return self.get_paginated_response(queryset)
return SuccessResponse(msg="获取成功", data=queryset, total=len(queryset))
def get_relation_info(self, request):
"""
查询关联的模板信息
"""
body = request.query_params
var_name = body.get('varName', None)
table = body.get('table', None)
instance = SystemConfig.objects.filter(key=var_name, setting__table=table).first()
if instance is None:
return ErrorResponse(msg="未获取到关联信息")
relation_id = body.get('relationIds', None)
relationIds = []
if relation_id is None:
return ErrorResponse(msg="未获取到关联信息")
if instance.form_item_type in [13]:
relationIds = [relation_id]
elif instance.form_item_type in [14]:
relationIds = relation_id.split(',')
queryset = SystemConfig.objects.filter(value__in=relationIds).first()
if queryset is None:
return ErrorResponse(msg="未获取到关联信息")
serializer = SystemConfigChinldernSerializer(queryset.parent)
return DetailResponse(msg="查询成功", data=serializer.data)
class InitSettingsViewSet(APIView):
"""
获取初始化配置
"""
authentication_classes = []
permission_classes = []
def filter_system_config_values(self, data: dict):
"""
过滤系统初始化配置
:param data:
:return:
"""
if not self.request.query_params.get('key', ''):
return data
new_data = {}
for key in self.request.query_params.get('key', '').split('|'):
if key:
new_data.update(**dict(filter(lambda x: x[0].startswith(key), data.items())))
return new_data
def get(self, request):
data = dispatch.get_system_config()
if not data:
dispatch.refresh_system_config()
data = dispatch.get_system_config()
# 不返回后端专用配置
backend_config = [f"{ele.get('parent__key')}.{ele.get('key')}" for ele in
SystemConfig.objects.filter(status=False, parent_id__isnull=False).values('parent__key',
'key')]
data = dict(filter(lambda x: x[0] not in backend_config, data.items()))
data = self.filter_system_config_values(data=data)
return DetailResponse(data=data)

View File

@@ -0,0 +1,365 @@
import hashlib
from django.contrib.auth.hashers import make_password, check_password
from django_restql.fields import DynamicSerializerMethodField
from rest_framework import serializers
from rest_framework.decorators import action, permission_classes
from rest_framework.permissions import IsAuthenticated
from django.db import connection
from application import dispatch
from dvadmin.system.models import Users, Role, Dept
from dvadmin.system.views.role import RoleSerializer
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomUniqueValidator
from dvadmin.utils.viewset import CustomModelViewSet
def recursion(instance, parent, result):
new_instance = getattr(instance, parent, None)
res = []
data = getattr(instance, result, None)
if data:
res.append(data)
if new_instance:
array = recursion(new_instance, parent, result)
res += (array)
return res
class UserSerializer(CustomModelSerializer):
"""
用户管理-序列化器
"""
dept_name = serializers.CharField(source='dept.name', read_only=True)
role_info = DynamicSerializerMethodField()
dept_name_all = serializers.SerializerMethodField()
class Meta:
model = Users
read_only_fields = ["id"]
exclude = ["password"]
extra_kwargs = {
"post": {"required": False},
"mobile": {"required": False},
}
def get_dept_name_all(self, instance):
dept_name_all = recursion(instance.dept, "parent", "name")
dept_name_all.reverse()
return "/".join(dept_name_all)
def get_role_info(self, instance, parsed_query):
roles = instance.role.all()
# You can do what ever you want in here
# `parsed_query` param is passed to BookSerializer to allow further querying
serializer = RoleSerializer(
roles,
many=True,
parsed_query=parsed_query
)
return serializer.data
class UserCreateSerializer(CustomModelSerializer):
"""
用户新增-序列化器
"""
username = serializers.CharField(
max_length=50,
validators=[
CustomUniqueValidator(queryset=Users.objects.all(), message="账号必须唯一")
],
)
password = serializers.CharField(
required=False,
)
def validate_password(self, value):
"""
对密码进行验证
"""
md5 = hashlib.md5()
md5.update(value.encode('utf-8'))
md5_password = md5.hexdigest()
return make_password(md5_password)
def save(self, **kwargs):
data = super().save(**kwargs)
data.dept_belong_id = data.dept_id
data.save()
data.post.set(self.initial_data.get("post", []))
return data
class Meta:
model = Users
fields = "__all__"
read_only_fields = ["id"]
extra_kwargs = {
"post": {"required": False},
"mobile": {"required": False},
}
class UserUpdateSerializer(CustomModelSerializer):
"""
用户修改-序列化器
"""
username = serializers.CharField(
max_length=50,
validators=[
CustomUniqueValidator(queryset=Users.objects.all(), message="账号必须唯一")
],
)
# password = serializers.CharField(required=False, allow_blank=True)
# mobile = serializers.CharField(
# max_length=50,
# validators=[
# CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一")
# ],
# allow_blank=True
# )
def save(self, **kwargs):
data = super().save(**kwargs)
data.dept_belong_id = data.dept_id
data.save()
data.post.set(self.initial_data.get("post", []))
return data
class Meta:
model = Users
read_only_fields = ["id", "password"]
fields = "__all__"
extra_kwargs = {
"post": {"required": False, "read_only": True},
"mobile": {"required": False},
}
class UserInfoUpdateSerializer(CustomModelSerializer):
"""
用户修改-序列化器
"""
mobile = serializers.CharField(
max_length=50,
validators=[
CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一")
],
allow_blank=True
)
def update(self, instance, validated_data):
return super().update(instance, validated_data)
class Meta:
model = Users
fields = ['email', 'mobile', 'avatar', 'name', 'gender']
extra_kwargs = {
"post": {"required": False, "read_only": True},
"mobile": {"required": False},
}
class ExportUserProfileSerializer(CustomModelSerializer):
"""
用户导出 序列化器
"""
last_login = serializers.DateTimeField(
format="%Y-%m-%d %H:%M:%S", required=False, read_only=True
)
is_active = serializers.SerializerMethodField(read_only=True)
dept_name = serializers.CharField(source="dept.name", default="")
dept_owner = serializers.CharField(source="dept.owner", default="")
gender = serializers.CharField(source="get_gender_display", read_only=True)
def get_is_active(self, instance):
return "启用" if instance.is_active else "停用"
class Meta:
model = Users
fields = (
"username",
"name",
"email",
"mobile",
"gender",
"is_active",
"last_login",
"dept_name",
"dept_owner",
)
class UserProfileImportSerializer(CustomModelSerializer):
password = serializers.CharField(read_only=True, required=False)
def save(self, **kwargs):
data = super().save(**kwargs)
password = hashlib.new(
"md5", str(self.initial_data.get("password", "admin123456")).encode(encoding="UTF-8")
).hexdigest()
data.set_password(password)
data.save()
return data
class Meta:
model = Users
exclude = (
"post",
"user_permissions",
"groups",
"is_superuser",
"date_joined",
)
class UserViewSet(CustomModelViewSet):
"""
用户接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Users.objects.exclude(is_superuser=1).all()
serializer_class = UserSerializer
create_serializer_class = UserCreateSerializer
update_serializer_class = UserUpdateSerializer
filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出
export_field_label = {
"username": "用户账号",
"name": "用户名称",
"email": "用户邮箱",
"mobile": "手机号码",
"gender": "用户性别",
"is_active": "帐号状态",
"last_login": "最后登录时间",
"dept_name": "部门名称",
"dept_owner": "部门负责人",
}
export_serializer_class = ExportUserProfileSerializer
# 导入
import_serializer_class = UserProfileImportSerializer
import_field_dict = {
"username": "登录账号",
"name": "用户名称",
"email": "用户邮箱",
"mobile": "手机号码",
"gender": {
"title": "用户性别",
"choices": {
"data": {"未知": 2, "": 1, "": 0},
}
},
"is_active": {
"title": "帐号状态",
"choices": {
"data": {"启用": True, "禁用": False},
}
},
"dept": {"title": "部门", "choices": {"queryset": Dept.objects.filter(status=True), "values_name": "name"}},
"role": {"title": "角色", "choices": {"queryset": Role.objects.filter(status=True), "values_name": "name"}},
}
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated])
def user_info(self, request):
"""获取当前用户信息"""
user = request.user
result = {
"id": user.id,
"username": user.username,
"name": user.name,
"mobile": user.mobile,
"user_type": user.user_type,
"gender": user.gender,
"email": user.email,
"avatar": user.avatar,
"dept": user.dept_id,
"is_superuser": user.is_superuser,
"role": user.role.values_list('id', flat=True),
}
if hasattr(connection, 'tenant'):
result['tenant_id'] = connection.tenant and connection.tenant.id
result['tenant_name'] = connection.tenant and connection.tenant.name
dept = getattr(user, 'dept', None)
if dept:
result['dept_info'] = {
'dept_id': dept.id,
'dept_name': dept.name
}
else:
result['dept_info'] = {
'dept_id': None,
'dept_name': "暂无部门"
}
role = getattr(user, 'role', None)
if role:
result['role_info'] = role.values('id', 'name', 'key')
return DetailResponse(data=result, msg="获取成功")
@action(methods=["PUT"], detail=False, permission_classes=[IsAuthenticated])
def update_user_info(self, request):
"""修改当前用户信息"""
serializer = UserInfoUpdateSerializer(request.user, data=request.data, request=request)
serializer.is_valid(raise_exception=True)
serializer.save()
return DetailResponse(data=None, msg="修改成功")
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
def change_password(self, request, *args, **kwargs):
"""密码修改"""
data = request.data
old_pwd = data.get("oldPassword")
new_pwd = data.get("newPassword")
new_pwd2 = data.get("newPassword2")
if old_pwd is None or new_pwd is None or new_pwd2 is None:
return ErrorResponse(msg="参数不能为空")
if new_pwd != new_pwd2:
return ErrorResponse(msg="两次密码不匹配")
verify_password = check_password(old_pwd, self.request.user.password)
if not verify_password:
verify_password = check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest(), self.request.user.password)
if verify_password:
request.user.password = make_password(new_pwd)
request.user.save()
return DetailResponse(data=None, msg="修改成功")
else:
return ErrorResponse(msg="旧密码不正确")
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
def reset_to_default_password(self, request, *args, **kwargs):
"""恢复默认密码"""
instance = Users.objects.filter(id=kwargs.get("pk")).first()
if instance:
instance.set_password(dispatch.get_system_config_values("base.default_password"))
instance.save()
return DetailResponse(data=None, msg="密码重置成功")
else:
return ErrorResponse(msg="未获取到用户")
@action(methods=["PUT"], detail=True)
def reset_password(self, request, pk):
"""
密码重置
"""
instance = Users.objects.filter(id=pk).first()
data = request.data
new_pwd = data.get("newPassword")
new_pwd2 = data.get("newPassword2")
if instance:
if new_pwd != new_pwd2:
return ErrorResponse(msg="两次密码不匹配")
else:
instance.password = make_password(new_pwd)
instance.save()
return DetailResponse(data=None, msg="修改成功")
else:
return ErrorResponse(msg="未获取到用户")