Merge remote-tracking branch 'origin/master'

This commit is contained in:
李强
2023-03-31 10:31:03 +08:00
312 changed files with 21647 additions and 25563 deletions

View File

@@ -0,0 +1,345 @@
# -*- coding: utf-8 -*-
import os
from rest_framework import serializers
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
import django
django.setup()
from dvadmin.system.models import Role, Dept, Users, Menu, MenuButton, ApiWhiteList, Dictionary, SystemConfig, \
RoleMenuPermission, RoleMenuButtonPermission
from dvadmin.utils.serializers import CustomModelSerializer
class UsersInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
def save(self, **kwargs):
instance = super().save(**kwargs)
role_key = self.initial_data.get('role_key', [])
role_ids = Role.objects.filter(key__in=role_key).values_list('id', flat=True)
instance.role.set(role_ids)
dept_key = self.initial_data.get('dept_key', None)
dept_id = Dept.objects.filter(key=dept_key).first()
instance.dept = dept_id
instance.save()
return instance
class Meta:
model = Users
fields = ["username", "email", 'mobile', 'avatar', "name", 'gender', 'user_type', "dept", 'user_type',
'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'creator', 'dept_belong_id',
'password', 'last_login', 'is_superuser']
read_only_fields = ['id']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class MenuButtonInitSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = MenuButton
fields = ['id', 'name', 'value', 'api', 'method', 'menu']
read_only_fields = ["id"]
class MenuInitSerializer(CustomModelSerializer):
"""
递归深度获取数信息(用于生成初始化json文件)
"""
name = serializers.CharField(required=False)
children = serializers.SerializerMethodField()
menu_button = serializers.SerializerMethodField()
def get_children(self, obj: Menu):
data = []
instance = Menu.objects.filter(parent_id=obj.id)
if instance:
serializer = MenuInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def get_menu_button(self, obj: Menu):
data = []
instance = obj.menuPermission.order_by('method')
if instance:
data = list(instance.values('name', 'value', 'api', 'method'))
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
menu_button = self.initial_data.get('menu_button')
# 菜单表
if children:
for menu_data in children:
menu_data['parent'] = instance.id
filter_data = {
"name": menu_data['name'],
"web_path": menu_data['web_path'],
"component": menu_data['component'],
"component_name": menu_data['component_name'],
}
instance_obj = Menu.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
# 菜单按钮
if menu_button:
for menu_button_data in menu_button:
menu_button_data['menu'] = instance.id
filter_data = {
"menu": menu_button_data['menu'],
"value": menu_button_data['value']
}
instance_obj = MenuButton.objects.filter(**filter_data).first()
serializer = MenuButtonInitSerializer(instance_obj, data=menu_button_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Menu
fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
read_only_fields = ['id', 'children']
class RoleInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
class Meta:
model = Role
fields = ['name', 'key', 'sort', 'status', 'admin',
'creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class RoleMenuInitSerializer(CustomModelSerializer):
"""
初始化角色菜单(用于生成初始化json文件)
"""
role_key = serializers.CharField(max_length=100,required=True)
menu_component_name = serializers.CharField(max_length=100,required=True)
def create(self, validated_data):
init_data = self.initial_data
validated_data.pop('menu_component_name')
validated_data.pop('role_key')
role_id = Role.objects.filter(key=init_data['role_key']).first()
menu_id = Menu.objects.filter(component_name=init_data['menu_component_name']).first()
validated_data['role'] = role_id
validated_data['menu'] = menu_id
return super().create(validated_data)
class Meta:
model = RoleMenuPermission
fields = ['role_key','menu_component_name','creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'role': {'required': False},
'menu': {'required': False},
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class RoleMenuButtonInitSerializer(CustomModelSerializer):
"""
初始化角色菜单按钮(用于生成初始化json文件)
"""
role_key = serializers.CharField(max_length=100,required=True)
menu_button_value = serializers.CharField(max_length=100,required=True)
data_range = serializers.CharField(max_length=100, required=False)
def create(self, validated_data):
init_data = self.initial_data
validated_data.pop('menu_button_value')
validated_data.pop('role_key')
role_id = Role.objects.filter(key=init_data['role_key']).first()
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button_value']).first()
validated_data['role'] = role_id
validated_data['menu_button'] = menu_button_id
instance = super().create(validated_data)
instance.dept.set([])
return instance
class Meta:
model = RoleMenuButtonPermission
fields = ['role_key','menu_button_value','data_range','dept','creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'role': {'required': False},
'menu': {'required': False},
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class ApiWhiteListInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
class Meta:
model = ApiWhiteList
fields = ['url', 'method', 'enable_datasource', 'creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class DeptInitSerializer(CustomModelSerializer):
"""
递归深度获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: Dept):
data = []
instance = Dept.objects.filter(parent_id=obj.id)
if instance:
serializer = DeptInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
if children:
for menu_data in children:
menu_data['parent'] = instance.id
filter_data = {
"name": menu_data['name'],
"parent": menu_data['parent'],
"key": menu_data['key']
}
instance_obj = Dept.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = DeptInitSerializer(instance_obj, data=menu_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Dept
fields = ['name', 'sort', 'owner', 'phone', 'email', 'status', 'parent', 'creator', 'dept_belong_id',
'children', 'key']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
read_only_fields = ['id', 'children']
class DictionaryInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: Dictionary):
data = []
instance = Dictionary.objects.filter(parent_id=obj.id)
if instance:
serializer = DictionaryInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
# 菜单表
if children:
for data in children:
data['parent'] = instance.id
filter_data = {
"value": data['value'],
"parent": data['parent']
}
instance_obj = Dictionary.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = DictionaryInitSerializer(instance_obj, data=data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Dictionary
fields = ['label', 'value', 'parent', 'type', 'color', 'is_value', 'status', 'sort', 'remark', 'creator',
'dept_belong_id', 'children']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class SystemConfigInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: SystemConfig):
data = []
instance = SystemConfig.objects.filter(parent_id=obj.id)
if instance:
serializer = SystemConfigInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
# 菜单表
if children:
for data in children:
data['parent'] = instance.id
filter_data = {
"key": data['key'],
"parent": data['parent']
}
instance_obj = SystemConfig.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = SystemConfigInitSerializer(instance_obj, data=data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = SystemConfig
fields = ['parent', 'title', 'key', 'value', 'sort', 'status', 'data_options', 'form_item_type', 'rule',
'placeholder', 'setting', 'creator', 'dept_belong_id', 'children']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}

View File

@@ -15,7 +15,7 @@
"value": "true",
"parent": 1,
"type": 6,
"color": null,
"color": "success",
"is_value": true,
"status": true,
"sort": 1,
@@ -27,7 +27,7 @@
"value": "false",
"parent": 1,
"type": 6,
"color": null,
"color": "danger",
"is_value": true,
"status": true,
"sort": 2,
@@ -50,7 +50,7 @@
{
"label": "新增",
"value": "Create",
"parent": 66,
"parent": 4,
"type": 0,
"color": "success",
"is_value": true,
@@ -62,7 +62,7 @@
{
"label": "编辑",
"value": "Update",
"parent": 66,
"parent": 4,
"type": 0,
"color": "primary",
"is_value": true,
@@ -74,7 +74,7 @@
{
"label": "删除",
"value": "Delete",
"parent": 66,
"parent": 4,
"type": 0,
"color": "danger",
"is_value": true,
@@ -86,7 +86,7 @@
{
"label": "详情",
"value": "Retrieve",
"parent": 66,
"parent": 4,
"type": 0,
"color": "info",
"is_value": true,
@@ -98,7 +98,7 @@
{
"label": "查询",
"value": "Search",
"parent": 66,
"parent": 4,
"type": 0,
"color": "warning",
"is_value": true,
@@ -110,7 +110,7 @@
{
"label": "保存",
"value": "Save",
"parent": 66,
"parent": 4,
"type": 0,
"color": "success",
"is_value": true,
@@ -122,7 +122,7 @@
{
"label": "导入",
"value": "Import",
"parent": 66,
"parent": 4,
"type": 0,
"color": "primary",
"is_value": true,
@@ -134,7 +134,7 @@
{
"label": "导出",
"value": "Export",
"parent": 66,
"parent": 4,
"type": 0,
"color": "warning",
"is_value": true,
@@ -159,9 +159,9 @@
{
"label": "启用",
"value": "1",
"parent": 7,
"parent": 13,
"type": 1,
"color": null,
"color": "success",
"is_value": true,
"status": true,
"sort": 1,
@@ -171,9 +171,9 @@
{
"label": "禁用",
"value": "0",
"parent": 7,
"parent": 13,
"type": 1,
"color": null,
"color": "danger",
"is_value": true,
"status": true,
"sort": 2,
@@ -196,9 +196,9 @@
{
"label": "是",
"value": "true",
"parent": 5,
"parent": 16,
"type": 6,
"color": null,
"color": "success",
"is_value": true,
"status": true,
"sort": 1,
@@ -208,9 +208,9 @@
{
"label": "否",
"value": "false",
"parent": 5,
"parent": 16,
"type": 6,
"color": null,
"color": "danger",
"is_value": true,
"status": true,
"sort": 2,
@@ -233,9 +233,9 @@
{
"label": "是",
"value": "1",
"parent": 10,
"parent": 19,
"type": 1,
"color": null,
"color": "success",
"is_value": true,
"status": true,
"sort": 1,
@@ -245,9 +245,9 @@
{
"label": "否",
"value": "2",
"parent": 10,
"parent": 19,
"type": 1,
"color": null,
"color": "danger",
"is_value": true,
"status": true,
"sort": 2,
@@ -270,7 +270,7 @@
{
"label": "后台用户",
"value": "0",
"parent": 15,
"parent": 22,
"type": 1,
"color": null,
"is_value": true,
@@ -282,7 +282,7 @@
{
"label": "前台用户",
"value": "1",
"parent": 15,
"parent": 22,
"type": 1,
"color": null,
"is_value": true,
@@ -307,7 +307,7 @@
{
"label": "text",
"value": "0",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -319,7 +319,7 @@
{
"label": "textarea",
"value": "3",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -331,7 +331,7 @@
{
"label": "number",
"value": "10",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -343,7 +343,7 @@
{
"label": "datetime",
"value": "1",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -355,7 +355,7 @@
{
"label": "date",
"value": "2",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -367,7 +367,7 @@
{
"label": "time",
"value": "15",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -379,7 +379,7 @@
{
"label": "select",
"value": "4",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -391,7 +391,7 @@
{
"label": "checkbox",
"value": "5",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -403,7 +403,7 @@
{
"label": "radio",
"value": "6",
"parent": 49,
"parent": 25,
"type": 1,
"color": null,
"is_value": true,
@@ -415,7 +415,7 @@
{
"label": "switch",
"value": "9",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -427,7 +427,7 @@
{
"label": "文件附件",
"value": "8",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -439,7 +439,7 @@
{
"label": "图片(单张)",
"value": "7",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -451,7 +451,7 @@
{
"label": "图片(多张)",
"value": "12",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -463,7 +463,7 @@
{
"label": "数组",
"value": "11",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -475,7 +475,7 @@
{
"label": "关联表",
"value": "13",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -487,7 +487,7 @@
{
"label": "关联表(多选)",
"value": "14",
"parent": 49,
"parent": 25,
"type": 1,
"color": "",
"is_value": true,
@@ -512,7 +512,7 @@
{
"label": "未知",
"value": "0",
"parent": 18,
"parent": 42,
"type": 1,
"color": null,
"is_value": true,
@@ -524,7 +524,7 @@
{
"label": "男",
"value": "1",
"parent": 18,
"parent": 42,
"type": 1,
"color": null,
"is_value": true,
@@ -536,7 +536,7 @@
{
"label": "女",
"value": "2",
"parent": 18,
"parent": 42,
"type": 1,
"color": null,
"is_value": true,
@@ -547,4 +547,4 @@
}
]
}
]
]

View File

@@ -1,13 +1,13 @@
[
{
"name": "系统管理",
"icon": "cog",
"icon": "iconfont icon-xitongshezhi",
"sort": 1,
"is_link": false,
"is_catalog": true,
"web_path": "",
"component": "",
"component_name": "",
"web_path": "/system",
"component": "layout/routerView/parent",
"component_name": "menu",
"status": true,
"cache": false,
"visible": true,
@@ -15,46 +15,46 @@
"children": [
{
"name": "菜单管理",
"icon": "navicon",
"icon": "iconfont icon-caidan",
"sort": 1,
"is_link": false,
"is_catalog": false,
"web_path": "/menu",
"component": "system/menu",
"component": "system/menu/index",
"component_name": "menu",
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "menu:Search",
"api": "/api/system/menu/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "menu:Retrieve",
"api": "/api/system/menu/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "menu:Create",
"api": "/api/system/menu/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "menu:Update",
"api": "/api/system/menu/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "menu:Delete",
"api": "/api/system/menu/{id}/",
"method": 3
}
@@ -72,30 +72,30 @@
"status": true,
"cache": false,
"visible": false,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "menu_button:Search",
"api": "/api/system/menu_button/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "menu_button:Create",
"api": "/api/system/menu_button/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "menu_button:Update",
"api": "/api/system/menu_button/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "menu_button:Delete",
"api": "/api/system/menu_button/{id}/",
"method": 3
}
@@ -103,7 +103,7 @@
},
{
"name": "部门管理",
"icon": "bank",
"icon": "ele-OfficeBuilding",
"sort": 3,
"is_link": false,
"is_catalog": false,
@@ -113,36 +113,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "dept:Search",
"api": "/api/system/dept/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "dept:Retrieve",
"api": "/api/system/dept/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "dept:Create",
"api": "/api/system/dept/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "dept:Update",
"api": "/api/system/dept/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "dept:Delete",
"api": "/api/system/dept/{id}/",
"method": 3
}
@@ -150,7 +150,7 @@
},
{
"name": "角色管理",
"icon": "address-book",
"icon": "ele-ColdDrink",
"sort": 4,
"is_link": false,
"is_catalog": false,
@@ -160,42 +160,42 @@
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "role:Search",
"api": "/api/system/role/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "role:Retrieve",
"api": "/api/system/role/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "role:Create",
"api": "/api/system/role/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "role:Update",
"api": "/api/system/role/{id}/",
"method": 2
},
{
"name": "保存",
"value": "Save",
"value": "role:Save",
"api": "/api/system/role/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "role:Delete",
"api": "/api/system/role/{id}/",
"method": 3
}
@@ -203,7 +203,7 @@
},
{
"name": "用户管理",
"icon": "users",
"icon": "iconfont icon-icon-",
"sort": 6,
"is_link": false,
"is_catalog": false,
@@ -213,60 +213,60 @@
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "user:Search",
"api": "/api/system/user/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "user:Retrieve",
"api": "/api/system/user/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "user:Create",
"api": "/api/system/user/",
"method": 1
},
{
"name": "导出",
"value": "Export",
"value": "user:Export",
"api": "/api/system/user/export/",
"method": 1
},
{
"name": "导入",
"value": "Import",
"value": "user:Import",
"api": "/api/system/user/import/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "user:Update",
"api": "/api/system/user/{id}/",
"method": 2
},
{
"name": "重设密码",
"value": "ResetPassword",
"value": "user:ResetPassword",
"api": "/api/system/user/{id}/reset_password/",
"method": 2
},
{
"name": "重置密码",
"value": "DefaultPassword",
"value": "user:DefaultPassword",
"api": "/api/system/user/{id}/reset_to_default_password/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "user:Delete",
"api": "/api/system/user/{id}/",
"method": 3
}
@@ -274,7 +274,7 @@
},
{
"name": "消息中心",
"icon": "bullhorn",
"icon": "iconfont icon-xiaoxizhongxin",
"sort": 7,
"is_link": false,
"is_catalog": false,
@@ -284,36 +284,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "messageCenter:Search",
"api": "/api/system/message_center/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "messageCenter:Retrieve",
"api": "/api/system/message_center/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "messageCenter:Create",
"api": "/api/system/message_center/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "messageCenter:Update",
"api": "/api/system/message_center/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "messageCenter:Delete",
"api": "/api/system/menu/{id}/",
"method": 3
}
@@ -321,7 +321,7 @@
},
{
"name": "接口白名单",
"icon": "compass",
"icon": "ele-SetUp",
"sort": 8,
"is_link": false,
"is_catalog": false,
@@ -331,36 +331,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 277,
"parent": 19,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "api_white_list:Search",
"api": "/api/system/api_white_list/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "api_white_list:Retrieve",
"api": "/api/system/api_white_list/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "api_white_list:Create",
"api": "/api/system/api_white_list/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "api_white_list:Update",
"api": "/api/system/api_white_list/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "api_white_list:Delete",
"api": "/api/system/api_white_list/{id}/",
"method": 3
}
@@ -371,13 +371,13 @@
},
{
"name": "常规配置",
"icon": "cogs",
"icon": "iconfont icon-configure",
"sort": 2,
"is_link": false,
"is_catalog": true,
"web_path": "",
"component": "",
"component_name": "",
"web_path": "/generalConfig",
"component": "layout/routerView/parent",
"component_name": "config",
"status": true,
"cache": false,
"visible": true,
@@ -385,7 +385,7 @@
"children": [
{
"name": "系统配置",
"icon": "desktop",
"icon": "iconfont icon-system",
"sort": 0,
"is_link": false,
"is_catalog": false,
@@ -395,36 +395,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 285,
"parent": 27,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "system_config:Search",
"api": "/api/system/system_config/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "system_config:Retrieve",
"api": "/api/system/system_config/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "system_config:Create",
"api": "/api/system/system_config/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "system_config:Update",
"api": "/api/system/system_config/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "system_config:Delete",
"api": "/api/system/system_config/{id}/",
"method": 3
}
@@ -432,7 +432,7 @@
},
{
"name": "字典管理",
"icon": "book",
"icon": "iconfont icon-dict",
"sort": 1,
"is_link": false,
"is_catalog": false,
@@ -442,36 +442,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 285,
"parent": 27,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "dictionary:Search",
"api": "/api/system/dictionary/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "dictionary:Retrieve",
"api": "/api/system/dictionary/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "dictionary:Create",
"api": "/api/system/dictionary/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "dictionary:Update",
"api": "/api/system/dictionary/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "dictionary:Delete",
"api": "/api/system/dictionary/{id}/",
"method": 3
}
@@ -479,7 +479,7 @@
},
{
"name": "地区管理",
"icon": "map",
"icon": "iconfont icon-Area",
"sort": 2,
"is_link": false,
"is_catalog": false,
@@ -489,36 +489,36 @@
"status": true,
"cache": false,
"visible": true,
"parent": 285,
"parent": 27,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "area:Search",
"api": "/api/system/area/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "area:Retrieve",
"api": "/api/system/area/{id}/",
"method": 0
},
{
"name": "新增",
"value": "Create",
"value": "area:Create",
"api": "/api/system/area/",
"method": 1
},
{
"name": "编辑",
"value": "Update",
"value": "area:Update",
"api": "/api/system/area/{id}/",
"method": 2
},
{
"name": "删除",
"value": "Delete",
"value": "area:Delete",
"api": "/api/system/area/{id}/",
"method": 3
}
@@ -526,7 +526,7 @@
},
{
"name": "附件管理",
"icon": "file-text-o",
"icon": "iconfont icon-file",
"sort": 3,
"is_link": false,
"is_catalog": false,
@@ -536,30 +536,30 @@
"status": true,
"cache": false,
"visible": true,
"parent": 285,
"parent": 27,
"children": [],
"menu_button": [
{
"name": "详情",
"value": "Retrieve",
"value": "file:Retrieve",
"api": "/api/system/file/{id}/",
"method": 0
},
{
"name": "查询",
"value": "Search",
"value": "file:Search",
"api": "/api/system/file/",
"method": 0
},
{
"name": "编辑",
"value": "Update",
"value": "file:Update",
"api": "/api/system/file/{id}/",
"method": 1
},
{
"name": "删除",
"value": "Delete",
"value": "file:Delete",
"api": "/api/system/file/{id}/",
"method": 3
}
@@ -570,13 +570,13 @@
},
{
"name": "日志管理",
"icon": "book",
"icon": "iconfont icon-rizhi",
"sort": 3,
"is_link": false,
"is_catalog": true,
"web_path": "",
"component": "",
"component_name": "",
"web_path": "/log",
"component": "layout/routerView/parent",
"component_name": "log",
"status": true,
"cache": false,
"visible": true,
@@ -584,7 +584,7 @@
"children": [
{
"name": "登录日志",
"icon": "file-text",
"icon": "iconfont icon-guanlidenglurizhi",
"sort": 1,
"is_link": false,
"is_catalog": false,
@@ -594,18 +594,18 @@
"status": true,
"cache": false,
"visible": true,
"parent": 290,
"parent": 32,
"children": [],
"menu_button": [
{
"name": "查询",
"value": "Search",
"value": "login_log:Search",
"api": "/api/system/login_log/",
"method": 0
},
{
"name": "详情",
"value": "Retrieve",
"value": "login_log:Retrieve",
"api": "/api/system/login_log/{id}/",
"method": 0
}
@@ -613,7 +613,7 @@
},
{
"name": "操作日志",
"icon": "file-code-o",
"icon": "iconfont icon-caozuorizhi",
"sort": 2,
"is_link": false,
"is_catalog": false,
@@ -623,56 +623,24 @@
"status": true,
"cache": false,
"visible": true,
"parent": 290,
"parent": 32,
"children": [],
"menu_button": [
{
"name": "详情",
"value": "Retrieve",
"value": "operation_log:Retrieve",
"api": "/api/system/operation_log/{id}/",
"method": 0
},
{
"name": "查询",
"value": "Search",
"value": "operation_log:Search",
"api": "/api/system/operation_log/",
"method": 0
}
]
},
{
"name": "前端错误日志",
"icon": "bug",
"sort": 4,
"is_link": false,
"is_catalog": false,
"web_path": "/frontendLog",
"component": "system/log/frontendLog/index",
"component_name": "frontendLog",
"status": true,
"cache": false,
"visible": true,
"parent": 290,
"children": [],
"menu_button": []
}
],
"menu_button": []
},
{
"name": "DVAdmin官网",
"icon": "external-link",
"sort": 4,
"is_link": true,
"is_catalog": false,
"web_path": "https://django-vue-admin.com",
"component": "",
"component_name": "",
"status": true,
"cache": false,
"visible": true,
"parent": null,
"children": [],
"menu_button": []
}
]
]

View File

@@ -5,7 +5,6 @@
"sort": 1,
"status": true,
"admin": true,
"data_range": 3,
"remark": null
},
{
@@ -14,7 +13,6 @@
"sort": 2,
"status": true,
"admin": true,
"data_range": 3,
"remark": null
}
]

View File

@@ -0,0 +1,12 @@
[
{
"role_key": "admin",
"menu_button_value": "menu:Search",
"data_range": 0
},
{
"role_key": "public",
"menu_button_value":"menu:Search",
"data_range": 0
}
]

View File

@@ -0,0 +1,10 @@
[
{
"role_key": "admin",
"menu_component_name": "menu"
},
{
"role_key": "public",
"menu_component_name": "menu"
}
]

View File

@@ -3,17 +3,14 @@ import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
django.setup()
from dvadmin.system.views.user import UsersInitSerializer
from dvadmin.system.views.menu import MenuInitSerializer
from dvadmin.utils.core_initialize import CoreInitialize
from dvadmin.system.views.role import RoleInitSerializer
from dvadmin.system.views.api_white_list import ApiWhiteListInitSerializer
from dvadmin.system.views.dept import DeptInitSerializer
from dvadmin.system.views.dictionary import DictionaryInitSerializer
from dvadmin.system.views.system_config import SystemConfigInitSerializer
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
class Initialize(CoreInitialize):
@@ -42,6 +39,19 @@ class Initialize(CoreInitialize):
"""
self.init_base(MenuInitSerializer, unique_fields=['name', 'web_path', 'component', 'component_name'])
def init_role_menu(self):
"""
初始化角色菜单信息
"""
self.init_base(RoleMenuInitSerializer, unique_fields=['role', 'menu'])
def init_role_menu_button(self):
"""
初始化角色菜单按钮信息
"""
self.init_base(RoleMenuButtonInitSerializer, unique_fields=['role', 'menu_button'])
def init_api_white_list(self):
"""
初始API白名单
@@ -65,6 +75,8 @@ class Initialize(CoreInitialize):
self.init_role()
self.init_users()
self.init_menu()
self.init_role_menu()
self.init_role_menu_button()
self.init_api_white_list()
self.init_dictionary()
self.init_system_config()

View File

@@ -5,20 +5,15 @@ import os
import django
from django.db.models import QuerySet
from dvadmin.system.views.system_config import SystemConfigInitSerializer
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
django.setup()
from django.core.management.base import BaseCommand
from application.settings import BASE_DIR
from dvadmin.system.models import Menu, Users, Dept, Role, ApiWhiteList, Dictionary, SystemConfig
from dvadmin.system.views.api_white_list import ApiWhiteListInitSerializer
from dvadmin.system.views.dept import DeptInitSerializer
from dvadmin.system.views.dictionary import DictionaryInitSerializer
from dvadmin.system.views.menu import MenuInitSerializer
from dvadmin.system.views.role import RoleInitSerializer
from dvadmin.system.views.user import UsersInitSerializer
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
logger = logging.getLogger(__name__)

View File

@@ -13,8 +13,9 @@ STATUS_CHOICES = (
)
class Users(CoreModel,AbstractUser):
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号")
class Users(CoreModel, AbstractUser):
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号",
help_text="用户账号")
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
@@ -34,8 +35,10 @@ class Users(CoreModel,AbstractUser):
user_type = models.IntegerField(
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="关联岗位")
role = models.ManyToManyField(to="Role", blank=True,verbose_name="关联角色", db_constraint=False, help_text="关联角色")
post = models.ManyToManyField(to="Post", blank=True, verbose_name="关联岗位", db_constraint=False,
help_text="关联岗位")
role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False,
help_text="关联角色")
dept = models.ForeignKey(
to="Dept",
verbose_name="所属部门",
@@ -79,20 +82,6 @@ class Role(CoreModel):
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态")
admin = models.BooleanField(default=False, verbose_name="是否为admin", help_text="是否为admin")
DATASCOPE_CHOICES = (
(0, "仅本人数据权限"),
(1, "本部门及以下数据权限"),
(2, "本部门数据权限"),
(3, "全部数据权限"),
(4, "自定数据权限"),
)
data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围")
remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
dept = models.ManyToManyField(to="Dept", verbose_name="数据权限-关联部门", db_constraint=False, help_text="数据权限-关联部门")
menu = models.ManyToManyField(to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单")
permission = models.ManyToManyField(
to="MenuButton", verbose_name="关联菜单的接口按钮", db_constraint=False, help_text="关联菜单的接口按钮"
)
class Meta:
db_table = table_prefix + "system_role"
@@ -103,7 +92,8 @@ class Role(CoreModel):
class Dept(CoreModel):
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="显示排序")
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="联系电话")
@@ -121,7 +111,7 @@ class Dept(CoreModel):
)
@classmethod
def recursion_dept_info(cls, dept_id: int, dept_all_list=None, dept_list=None):
def recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):
"""
递归获取部门的所有下级部门
:param dept_id: 需要获取的id
@@ -136,7 +126,7 @@ class Dept(CoreModel):
for ele in dept_all_list:
if ele.get("parent") == dept_id:
dept_list.append(ele.get("id"))
cls.recursion_dept_info(ele.get("id"), dept_all_list, dept_list)
cls.recursion_all_dept(ele.get("id"), dept_all_list, dept_list)
return list(set(dept_list))
class Meta:
@@ -167,10 +157,12 @@ class Menu(CoreModel):
is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")
component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True, help_text="组件名称")
component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True,
help_text="组件名称")
status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示", help_text="侧边栏中是否显示")
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
help_text="侧边栏中是否显示")
class Meta:
db_table = table_prefix + "system_menu"
@@ -189,7 +181,7 @@ class MenuButton(CoreModel):
help_text="关联菜单",
)
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值")
value = models.CharField(unique=True, max_length=64, verbose_name="权限值", help_text="权限值")
api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")
METHOD_CHOICES = (
(0, "GET"),
@@ -197,7 +189,8 @@ class MenuButton(CoreModel):
(2, "PUT"),
(3, "DELETE"),
)
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,
help_text="接口请求方法")
class Meta:
db_table = table_prefix + "system_menu_button"
@@ -206,6 +199,69 @@ class MenuButton(CoreModel):
ordering = ("-name",)
class RoleMenuPermission(CoreModel):
role = models.ForeignKey(
to="Role",
db_constraint=False,
related_name="role_menu",
on_delete=models.CASCADE,
verbose_name="关联角色",
help_text="关联角色",
)
menu = models.ForeignKey(
to="Menu",
db_constraint=False,
related_name="role_menu",
on_delete=models.CASCADE,
verbose_name="关联菜单",
help_text="关联菜单",
)
class Meta:
db_table = table_prefix + "role_menu_permission"
verbose_name = "角色菜单权限表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
class RoleMenuButtonPermission(CoreModel):
role = models.ForeignKey(
to="Role",
db_constraint=False,
related_name="role_menu_button",
on_delete=models.CASCADE,
verbose_name="关联角色",
help_text="关联角色",
)
menu_button = models.ForeignKey(
to="MenuButton",
db_constraint=False,
related_name="menu_button_permission",
on_delete=models.CASCADE,
verbose_name="关联菜单按钮",
help_text="关联菜单按钮",
null=True,
blank=True
)
DATASCOPE_CHOICES = (
(0, "仅本人数据权限"),
(1, "本部门及以下数据权限"),
(2, "本部门数据权限"),
(3, "全部数据权限"),
(4, "自定数据权限"),
)
data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围",
help_text="数据权限范围")
dept = models.ManyToManyField(to="Dept", blank=True, verbose_name="数据权限-关联部门", db_constraint=False,
help_text="数据权限-关联部门")
class Meta:
db_table = table_prefix + "role_menu_button_permission"
verbose_name = "角色按钮权限表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
class Dictionary(CoreModel):
TYPE_LIST = (
(0, "text"),
@@ -218,7 +274,8 @@ class Dictionary(CoreModel):
(7, "images"),
)
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值")
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号",
help_text="字典编号/实际值")
parent = models.ForeignKey(
to="self",
related_name="sublist",
@@ -231,7 +288,8 @@ class Dictionary(CoreModel):
)
type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型")
color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色")
is_value = models.BooleanField(default=False, verbose_name="是否为value值", help_text="是否为value值,用来做具体值存放")
is_value = models.BooleanField(default=False, verbose_name="是否为value值",
help_text="是否为value值,用来做具体值存放")
status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
@@ -253,14 +311,20 @@ class Dictionary(CoreModel):
class OperationLog(CoreModel):
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址")
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True,
help_text="请求模块")
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True,
help_text="请求地址")
request_body = models.TextField(verbose_name="请求参数", null=True, blank=True, help_text="请求参数")
request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True, help_text="请求方式")
request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True,
help_text="请求方式")
request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")
request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True, help_text="请求ip地址")
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True, help_text="请求浏览器")
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码")
request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True,
help_text="请求ip地址")
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True,
help_text="请求浏览器")
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True,
help_text="响应状态码")
request_os = models.CharField(max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
json_result = models.TextField(verbose_name="返回信息", null=True, blank=True, help_text="返回信息")
status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")
@@ -301,7 +365,8 @@ class FileList(CoreModel):
class Area(CoreModel):
name = models.CharField(max_length=100, verbose_name="名称", help_text="名称")
code = models.CharField(max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True)
level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)", help_text="地区层级(1省份 2城市 3区县 4乡级)")
level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)",
help_text="地区层级(1省份 2城市 3区县 4乡级)")
pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音")
initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")
enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用")
@@ -334,8 +399,10 @@ class ApiWhiteList(CoreModel):
(2, "PUT"),
(3, "DELETE"),
)
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True)
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,
help_text="接口请求方法")
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限",
blank=True)
class Meta:
db_table = table_prefix + "api_white_list"
@@ -419,11 +486,13 @@ class LoginLog(CoreModel):
district = models.CharField(max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区")
isp = models.CharField(max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商")
area_code = models.CharField(max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码")
country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True, help_text="英文全称")
country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True,
help_text="英文全称")
country_code = models.CharField(max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称")
longitude = models.CharField(max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度")
latitude = models.CharField(max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度")
login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型")
login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型",
help_text="登录类型")
class Meta:
db_table = table_prefix + "system_login_log"
@@ -433,14 +502,16 @@ class LoginLog(CoreModel):
class MessageCenter(CoreModel):
title = models.CharField(max_length=100,verbose_name="标题",help_text="标题")
content = models.TextField(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_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,
verbose_name="目标部门", help_text="目标部门")
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
verbose_name="目标角色", help_text="目标角色")
title = models.CharField(max_length=100, verbose_name="标题", help_text="标题")
content = models.TextField(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_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,
verbose_name="目标部门", help_text="目标部门")
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
verbose_name="目标角色", help_text="目标角色")
class Meta:
db_table = table_prefix + "message_center"
@@ -448,12 +519,15 @@ class MessageCenter(CoreModel):
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
class MessageCenterTargetUser(CoreModel):
users = models.ForeignKey(Users,related_name="target_user", on_delete=models.CASCADE,db_constraint=False,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="是否已读")
users = models.ForeignKey(Users, related_name="target_user", on_delete=models.CASCADE, db_constraint=False,
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:
db_table = table_prefix + "message_center_target_user"
verbose_name = "消息中心目标用户表"
verbose_name_plural = verbose_name
verbose_name_plural = verbose_name

View File

@@ -0,0 +1 @@
from django.test import TestCase

View File

@@ -12,6 +12,8 @@ from dvadmin.system.views.menu_button import MenuButtonViewSet
from dvadmin.system.views.message_center import MessageCenterViewSet
from dvadmin.system.views.operation_log import OperationLogViewSet
from dvadmin.system.views.role import RoleViewSet
from dvadmin.system.views.role_menu import RoleMenuPermissionViewSet
from dvadmin.system.views.role_menu_button_permission import RoleMenuButtonPermissionViewSet
from dvadmin.system.views.system_config import SystemConfigViewSet
from dvadmin.system.views.user import UserViewSet
@@ -28,6 +30,11 @@ system_url.register(r'file', FileViewSet)
system_url.register(r'api_white_list', ApiWhiteListViewSet)
system_url.register(r'system_config', SystemConfigViewSet)
system_url.register(r'message_center',MessageCenterViewSet)
system_url.register(r'role_menu_button_permission', RoleMenuButtonPermissionViewSet)
system_url.register(r'role_menu_permission', RoleMenuPermissionViewSet)
urlpatterns = [
path('user/export/', UserViewSet.as_view({'post': 'export_data', })),

View File

@@ -22,19 +22,7 @@ class ApiWhiteListSerializer(CustomModelSerializer):
read_only_fields = ["id"]
class ApiWhiteListInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
class Meta:
model = ApiWhiteList
fields = ['url', 'method', 'enable_datasource', 'creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class ApiWhiteListViewSet(CustomModelViewSet):

View File

@@ -13,10 +13,14 @@ 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__"
@@ -44,4 +48,24 @@ class AreaViewSet(CustomModelViewSet):
"""
queryset = Area.objects.all()
serializer_class = AreaSerializer
extra_filter_backends = []
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

@@ -7,6 +7,7 @@
"""
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from dvadmin.system.models import Dept
from dvadmin.utils.json_response import DetailResponse, SuccessResponse
@@ -55,49 +56,7 @@ class DeptImportSerializer(CustomModelSerializer):
read_only_fields = ["id"]
class DeptInitSerializer(CustomModelSerializer):
"""
递归深度获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: Dept):
data = []
instance = Dept.objects.filter(parent_id=obj.id)
if instance:
serializer = DeptInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
if children:
for menu_data in children:
menu_data['parent'] = instance.id
filter_data = {
"name": menu_data['name'],
"parent": menu_data['parent'],
"key": menu_data['key']
}
instance_obj = Dept.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = DeptInitSerializer(instance_obj, data=menu_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Dept
fields = ['name', 'sort', 'owner', 'phone', 'email', 'status', 'parent', 'creator', 'dept_belong_id',
'children', 'key']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
read_only_fields = ['id', 'children']
class DeptCreateUpdateSerializer(CustomModelSerializer):
@@ -134,7 +93,7 @@ class DeptViewSet(CustomModelViewSet):
update_serializer_class = DeptCreateUpdateSerializer
filter_fields = ['name', 'id', 'parent']
search_fields = []
# extra_filter_backends = []
# extra_filter_class = []
import_serializer_class = DeptImportSerializer
import_field_dict = {
"name": "部门名称",
@@ -143,8 +102,15 @@ class DeptViewSet(CustomModelViewSet):
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)
@@ -182,7 +148,7 @@ class DeptViewSet(CustomModelViewSet):
return DetailResponse(data=queryset, msg="获取成功")
@action(methods=["GET"], detail=False, permission_classes=[AnonymousUserPermission])
@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')

View File

@@ -27,48 +27,7 @@ class DictionarySerializer(CustomModelSerializer):
read_only_fields = ["id"]
class DictionaryInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: Dictionary):
data = []
instance = Dictionary.objects.filter(parent_id=obj.id)
if instance:
serializer = DictionaryInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
# 菜单表
if children:
for data in children:
data['parent'] = instance.id
filter_data = {
"value": data['value'],
"parent": data['parent']
}
instance_obj = Dictionary.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = DictionaryInitSerializer(instance_obj, data=data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Dictionary
fields = ['label', 'value', 'parent', 'type', 'color', 'is_value', 'status', 'sort', 'remark', 'creator',
'dept_belong_id', 'children']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class DictionaryCreateUpdateSerializer(CustomModelSerializer):
@@ -92,9 +51,21 @@ class DictionaryViewSet(CustomModelViewSet):
"""
queryset = Dictionary.objects.all()
serializer_class = DictionarySerializer
extra_filter_backends = []
extra_filter_class = []
search_fields = ['label']
def get_queryset(self):
params = self.request.query_params
parent = params.get('parent', None)
if params:
if parent:
queryset = self.queryset.filter(status=1, parent=parent)
else:
queryset = self.queryset.filter(status=1, parent__isnull=True)
else:
queryset = self.queryset.filter(status=1, parent__isnull=True)
return queryset
class InitDictionaryViewSet(APIView):
"""

View File

@@ -5,6 +5,7 @@ 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.contrib.auth.hashers import make_password, check_password
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi
@@ -54,11 +55,9 @@ 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__"
@@ -91,12 +90,13 @@ class LoginSerializer(TokenObtainPairSerializer):
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,
'dept_key': dept.key
}
role = getattr(self.user, 'role', None)
if role:
@@ -107,15 +107,78 @@ class LoginSerializer(TokenObtainPairSerializer):
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):
"""

View File

@@ -33,4 +33,4 @@ class LoginLogViewSet(CustomModelViewSet):
"""
queryset = LoginLog.objects.all()
serializer_class = LoginLogSerializer
extra_filter_backends = []
extra_filter_class = []

View File

@@ -9,8 +9,7 @@
from rest_framework import serializers
from rest_framework.decorators import action
from dvadmin.system.models import Menu, MenuButton
from dvadmin.system.views.menu_button import MenuButtonInitSerializer
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
@@ -54,72 +53,7 @@ class MenuCreateSerializer(CustomModelSerializer):
read_only_fields = ["id"]
class MenuInitSerializer(CustomModelSerializer):
"""
递归深度获取数信息(用于生成初始化json文件)
"""
name = serializers.CharField(required=False)
children = serializers.SerializerMethodField()
menu_button = serializers.SerializerMethodField()
def get_children(self, obj: Menu):
data = []
instance = Menu.objects.filter(parent_id=obj.id)
if instance:
serializer = MenuInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def get_menu_button(self, obj: Menu):
data = []
instance = obj.menuPermission.order_by('method')
if instance:
data = list(instance.values('name', 'value', 'api', 'method'))
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
menu_button = self.initial_data.get('menu_button')
# 菜单表
if children:
for menu_data in children:
menu_data['parent'] = instance.id
filter_data = {
"name": menu_data['name'],
"web_path": menu_data['web_path'],
"component": menu_data['component'],
"component_name": menu_data['component_name'],
}
instance_obj = Menu.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
# 菜单按钮
if menu_button:
for menu_button_data in menu_button:
menu_button_data['menu'] = instance.id
filter_data = {
"menu": menu_button_data['menu'],
"value": menu_button_data['value']
}
instance_obj = MenuButton.objects.filter(**filter_data).first()
serializer = MenuButtonInitSerializer(instance_obj, data=menu_button_data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = Menu
fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
read_only_fields = ['id', 'children']
class WebRouterSerializer(CustomModelSerializer):
@@ -128,25 +62,12 @@ class WebRouterSerializer(CustomModelSerializer):
"""
path = serializers.CharField(source="web_path")
title = serializers.CharField(source="name")
menuPermission = serializers.SerializerMethodField(read_only=True)
def get_menuPermission(self, instance):
# 判断是否是超级管理员
if self.request.user.is_superuser:
return instance.menuPermission.values_list('value', flat=True)
else:
# 根据当前角色获取权限按钮id集合
permissionIds = self.request.user.role.values_list('permission', flat=True)
queryset = instance.menuPermission.filter(id__in=permissionIds, menu=instance.id).values_list('value', flat=True)
if queryset:
return queryset
else:
return None
class Meta:
model = Menu
fields = ('id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
'component_name', 'cache', 'visible', 'menuPermission')
'component_name', 'cache', 'visible')
read_only_fields = ["id"]
@@ -165,7 +86,7 @@ class MenuViewSet(CustomModelViewSet):
update_serializer_class = MenuCreateSerializer
search_fields = ['name', 'status']
filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog']
# extra_filter_backends = []
# extra_filter_class = []
@action(methods=['GET'], detail=False, permission_classes=[])
def web_router(self, request):
@@ -173,16 +94,24 @@ class MenuViewSet(CustomModelViewSet):
user = request.user
queryset = self.queryset.filter(status=1)
if not user.is_superuser:
menuIds = user.role.values_list('menu__id', flat=True)
queryset = Menu.objects.filter(id__in=menuIds, status=1)
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="获取成功")
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(status=1, parent=parent)

View File

@@ -6,7 +6,12 @@
@Created on: 2021/6/3 003 0:30
@Remark: 菜单按钮管理
"""
from dvadmin.system.models import MenuButton
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
@@ -22,15 +27,7 @@ class MenuButtonSerializer(CustomModelSerializer):
read_only_fields = ["id"]
class MenuButtonInitSerializer(CustomModelSerializer):
"""
初始化菜单按钮-序列化器
"""
class Meta:
model = MenuButton
fields = ['id', 'name', 'value', 'api', 'method', 'menu']
read_only_fields = ["id"]
class MenuButtonCreateUpdateSerializer(CustomModelSerializer):
"""
@@ -56,4 +53,20 @@ class MenuButtonViewSet(CustomModelViewSet):
serializer_class = MenuButtonSerializer
create_serializer_class = MenuButtonCreateUpdateSerializer
update_serializer_class = MenuButtonCreateUpdateSerializer
extra_filter_backends = []
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

@@ -86,7 +86,9 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
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()
return queryset.is_read
if queryset:
return queryset.is_read
return False
class Meta:
model = MessageCenter
@@ -121,12 +123,12 @@ class MessageCenterCreateSerializer(CustomModelSerializer):
users = initial_data.get('target_user', [])
if target_type in [1]: # 按角色
target_role = initial_data.get('target_role',[])
users = Users.objects.exclude(is_deleted=True).filter(role__id__in=target_role).values_list('id', flat=True)
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.exclude(is_deleted=True).filter(dept__id__in=target_dept).values_list('id', flat=True)
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
if target_type in [3]: # 系统通知
users = Users.objects.exclude(is_deleted=True).values_list('id', flat=True)
users = Users.objects.values_list('id', flat=True)
targetuser_data = []
for user in users:
targetuser_data.append({
@@ -211,6 +213,6 @@ class MessageCenterViewSet(CustomModelViewSet):
queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('create_datetime').last()
data = None
if queryset:
serializer = MessageCenterTargetUserListSerializer(queryset, many=False, request=request)
serializer = MessageCenterTargetUserListSerializer(queryset.messagecenter, many=False, request=request)
data = serializer.data
return DetailResponse(data=data, msg="获取成功")

View File

@@ -14,6 +14,7 @@ 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
@@ -31,20 +32,7 @@ class RoleSerializer(CustomModelSerializer):
read_only_fields = ["id"]
class RoleInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
class Meta:
model = Role
fields = ['name', 'key', 'sort', 'status', 'admin', 'data_range', 'remark',
'creator', 'dept_belong_id']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class RoleCreateUpdateSerializer(CustomModelSerializer):
@@ -66,9 +54,6 @@ class RoleCreateUpdateSerializer(CustomModelSerializer):
if not is_superuser:
self.validated_data.pop('admin')
data = super().save(**kwargs)
data.dept.set(self.initial_data.get('dept', []))
data.menu.set(self.initial_data.get('menu', []))
data.permission.set(self.initial_data.get('permission', []))
return data
class Meta:
@@ -97,7 +82,7 @@ class MenuPermissonSerializer(CustomModelSerializer):
fields = ['id', 'parent', 'name', 'menuPermission']
class RoleViewSet(CustomModelViewSet):
class RoleViewSet(CustomModelViewSet,FastCrudMixin):
"""
角色管理接口
list:查询
@@ -111,107 +96,3 @@ class RoleViewSet(CustomModelViewSet):
create_serializer_class = RoleCreateUpdateSerializer
update_serializer_class = RoleCreateUpdateSerializer
search_fields = ['name', 'key']
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def role_get_menu(self, request):
"""根据当前用户的角色返回角色拥有的菜单"""
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).all()
else:
menu_id_list = request.user.role.values_list('menu',flat=True)
queryset = Menu.objects.filter(id__in=menu_id_list)
# queryset = self.filter_queryset(queryset)
serializer = MenuPermissonSerializer(queryset, many=True,request=request)
return DetailResponse(data=serializer.data)
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def data_scope(self, request):
is_superuser = request.user.is_superuser
role_queryset = Role.objects.filter(users__id=request.user.id).values_list('data_range', flat=True)
if is_superuser:
data = [
{
"value": 0,
"label": '仅本人数据权限'
},
{
"value": 1,
"label": '本部门及以下数据权限'
},
{
"value": 2,
"label": '本部门数据权限'
},
{
"value": 3,
"label": '全部数据权限'
},
{
"value": 4,
"label": '自定义数据权限'
}
]
else:
data = []
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)
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def data_scope_dept(self,request):
"""根据当前角色获取部门信息"""
is_superuser = request.user.is_superuser
if is_superuser:
queryset = Dept.objects.values('id','name','parent')
else:
dept_list = request.user.role.values_list('dept',flat=True)
queryset = Dept.objects.filter(id__in=dept_list).values('id','name','parent')
return DetailResponse(data=queryset)

View File

@@ -0,0 +1,79 @@
# -*- 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="未获取到菜单参数")
data = [{"role":role_id,"menu":item} for item in menu_list]
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,244 @@
# -*- 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 RoleMenuButtonPermission, Menu, MenuButton, Dept
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):
"""
初始化菜单按钮-序列化器
"""
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):
"""根据当前用户的角色返回角色拥有的菜单"""
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('id','name','parent','is_catalog')
else:
role_id = request.user.role.values_list('id',flat=True)
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_id).values(id=F('menu__id'),name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog'))
return DetailResponse(data=queryset)
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
def role_menu_get_button(self,request):
"""
当前用户角色和菜单获取可下拉选项的按钮:角色授权页面使用
:param request:
:return:
"""
params = request.query_params
if params:
menu_id = params.get('menu',None)
if menu_id:
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(
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_id = request.user.role.id
params = request.query_params
if params:
menu_button_id = params.get('menu_button', None)
if menu_button_id:
role_queryset = RoleMenuButtonPermission.objects.filter(role=role_id,menu_button=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')
return DetailResponse(data=queryset)
else:
if params:
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(
id=F('dept__id'),
name=F('dept__name'),
parent=F('dept__parent')
)
return DetailResponse(data=queryset)
else:
return ErrorResponse(msg="参数错误")
@action(methods=['get'],detail=False,permission_classes=[IsAuthenticated])
def menu_to_button(self,request):
"""
根据所选择菜单获取已配置的按钮/接口权限:角色授权页面使用
:param request:
:return:
"""
params = request.query_params
if params:
menu_id = params.get('menu',None)
if menu_id is None:
return ErrorResponse(msg="未获取到参数")
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'
)
return DetailResponse(data=queryset)
return ErrorResponse(msg="未获取到参数")

View File

@@ -43,48 +43,6 @@ class SystemConfigCreateSerializer(CustomModelSerializer):
return value
class SystemConfigInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
children = serializers.SerializerMethodField()
def get_children(self, obj: SystemConfig):
data = []
instance = SystemConfig.objects.filter(parent_id=obj.id)
if instance:
serializer = SystemConfigInitSerializer(instance=instance, many=True)
data = serializer.data
return data
def save(self, **kwargs):
instance = super().save(**kwargs)
children = self.initial_data.get('children')
# 菜单表
if children:
for data in children:
data['parent'] = instance.id
filter_data = {
"key": data['key'],
"parent": data['parent']
}
instance_obj = SystemConfig.objects.filter(**filter_data).first()
if instance_obj and not self.initial_data.get('reset'):
continue
serializer = SystemConfigInitSerializer(instance_obj, data=data, request=self.request)
serializer.is_valid(raise_exception=True)
serializer.save()
return instance
class Meta:
model = SystemConfig
fields = ['parent', 'title', 'key', 'value', 'sort', 'status', 'data_options', 'form_item_type', 'rule',
'placeholder', 'setting', 'creator', 'dept_belong_id', 'children']
read_only_fields = ["id"]
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class SystemConfigSerializer(CustomModelSerializer):
@@ -103,10 +61,10 @@ class SystemConfigChinldernSerializer(CustomModelSerializer):
"""
系统配置子级-序列化器
"""
chinldern = serializers.SerializerMethodField()
children = serializers.SerializerMethodField()
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
def get_chinldern(self, instance):
def get_children(self, instance):
queryset = SystemConfig.objects.filter(parent=instance)
serializer = SystemConfigSerializer(queryset, many=True)
return serializer.data

View File

@@ -60,32 +60,7 @@ class UserSerializer(CustomModelSerializer):
return serializer.data
class UsersInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
def save(self, **kwargs):
instance = super().save(**kwargs)
role_key = self.initial_data.get('role_key', [])
role_ids = Role.objects.filter(key__in=role_key).values_list('id', flat=True)
instance.role.set(role_ids)
dept_key = self.initial_data.get('dept_key', None)
dept_id = Dept.objects.filter(key=dept_key).first()
instance.dept = dept_id
instance.save()
return instance
class Meta:
model = Users
fields = ["username", "email", 'mobile', 'avatar', "name", 'gender', 'user_type', "dept", 'user_type',
'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'creator', 'dept_belong_id',
'password', 'last_login', 'is_superuser']
read_only_fields = ['id']
extra_kwargs = {
'creator': {'write_only': True},
'dept_belong_id': {'write_only': True}
}
class UserCreateSerializer(CustomModelSerializer):
@@ -253,16 +228,7 @@ class UserViewSet(CustomModelViewSet):
serializer_class = UserSerializer
create_serializer_class = UserCreateSerializer
update_serializer_class = UserUpdateSerializer
# filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
filter_fields = {
"name": ["exact"],
"mobile": ["exact"],
"username": ["exact"],
"gender": ["icontains"],
"is_active": ["icontains"],
"dept": ["exact"],
"user_type": ["exact"],
}
filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出
export_field_label = {
@@ -355,6 +321,7 @@ class UserViewSet(CustomModelViewSet):
if not check_password:
check_password = request.user.check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest())
if check_password:
new_pwd = hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest()
request.user.password = make_password(new_pwd)
request.user.save()
return DetailResponse(data=None, msg="修改成功")

View File

@@ -33,6 +33,7 @@ class CoreInitialize:
path_file = os.path.join(apps.get_app_config(self.app.split('.')[-1]).path, 'fixtures',
f'init_{Serializer.Meta.model._meta.model_name}.json')
if not os.path.isfile(path_file):
print("文件不存在,跳过初始化")
return
with open(path_file,encoding="utf-8") as f:
for data in json.load(f):

View File

@@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from dvadmin.utils.json_response import DetailResponse
class FastCrudMixin:
"""
定义快速CRUD数据操作的通用方法
"""
# 需要CRUD的字段
crud_fields = None
# 排除CRUD的字段
exclude_fields = None
# 自定义CRUD的JSON
custom_crud_json = None
# 需要修改的CRUD键值对
crud_update_key_value = None
# 将Django的字段类型处理为JS类型
def __handle_type(self, type):
if type in ['BigAutoField', 'CharField']:
return "input"
if type == 'DateTimeField':
return "datetime"
if type == 'DateField':
return "date"
if type == 'IntegerField':
return "number"
if type == 'BooleanField':
return "dict-switch"
# 获取字段属性信息
def __get_field_attribute(self):
result = []
queryset = self.get_queryset()
__name = ""
__verbose_name = ""
__type = "text"
# 判断指定CRUD字段
if self.crud_fields and type(self.crud_fields == list):
for item in self.crud_fields:
try:
field = queryset.model._meta.get_field(item)
field_type = field.get_internal_type()
__name = field.name
# 判断类型是否为外键类型,外键类型需要特殊方式获取verbose_name
if field_type in ['ForeignKey', 'OneToOneField', 'ManyToManyField']:
continue
# try:
# verbose_name = Users._meta.get_field(str(field.name)).verbose_name
# except:
# pass
else:
__verbose_name = field.verbose_name
__type = self.__handle_type(field_type)
except:
continue
result.append({"key": __name, "title": __verbose_name, "type": __type})
else:
# 获取model的所有字段及属性
model_fields = queryset.model._meta.get_fields()
# 遍历所有字段属性
for field in model_fields:
field_type = field.get_internal_type()
__name = field.name
# 判断需要排除的CRUD字段
if self.exclude_fields and type(self.exclude_fields == list):
if __name in self.exclude_fields:
continue
# 判断类型是否为外键类型,外键类型需要特殊方式获取verbose_name
if field_type in ['ForeignKey', 'OneToOneField', 'ManyToManyField']:
continue
# try:
# verbose_name = Users._meta.get_field(str(field.name)).verbose_name
# except:
# pass
else:
__verbose_name = field.verbose_name
__type = self.__handle_type(field_type)
result.append({"key": __name, "title": __verbose_name, "type": __type})
return result
#获取key
def __find_key(self,dct: dict,
target_key: str,
level: int = -1,
index: int = -1) -> tuple:
"""Find a key within a nested dictionary and return its level and index."""
for k, v in dct.items():
level += 1
index += 1
if k == target_key:
return level, index
elif isinstance(v, list):
for i, dct_ in enumerate(v):
if isinstance(dct_, dict):
result = self.__find_key(dct_, target_key)
if result is not None:
return result
else:
continue
elif isinstance(v, str) or isinstance(v, int) or isinstance(v, float):
continue
# 修改字典中key的value
def __update_nested_dict(self,nested_dict: dict,
target_key: str,
new_value) -> dict:
"""Update a nested dictionary with a new value."""
split_target_key = target_key.split('.')
if len(split_target_key) > 1:
new_dict = nested_dict[split_target_key[0]]
for item in split_target_key[1:-1]:
new_dict = new_dict[item]
self.__update_nested_dict(new_dict, split_target_key[-1], new_value)
else:
nested_dict[target_key] = new_value
return nested_dict
# 处理crud,返回columns
def __handle_crud(self):
result = self.__get_field_attribute()
columns = dict()
for item in result:
key = item.get('key')
title = item.get('title')
type = item.get('type')
columns[key] = {
"title": title,
"key": key,
"type": type
}
# 对自定义的crud配置合并
if self.custom_crud_json and isinstance(self.custom_crud_json,dict):
columns = columns | self.custom_crud_json
# 对curd进行修改配置
if self.crud_update_key_value and isinstance(self.crud_update_key_value,dict):
for key, value in self.crud_update_key_value.items():
columns = self.__update_nested_dict(columns,key,value)
return columns
@action(methods=['get'], detail=False,permission_classes=[AllowAny])
def init_crud(self, request):
self.permission_classes = [AllowAny]
columns = self.__handle_crud()
expose = "({expose,dict})=>{"
ret = "return {"
res = "}}"
data = f"""{expose}
{ret}
columns:{columns}
{res}
"""
return DetailResponse(data=data)

View File

@@ -11,14 +11,19 @@ import traceback
from django.db.models import ProtectedError
from django.http import Http404
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
from rest_framework.views import set_rollback
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed, NotAuthenticated
from rest_framework.status import HTTP_401_UNAUTHORIZED
from rest_framework.views import set_rollback, exception_handler
from dvadmin.utils.json_response import ErrorResponse
logger = logging.getLogger(__name__)
class CustomAuthenticationFailed(NotAuthenticated):
# 设置 status_code 属性为 400
status_code = 400
def CustomExceptionHandler(ex, context):
"""
统一异常拦截处理
@@ -30,9 +35,14 @@ def CustomExceptionHandler(ex, context):
"""
msg = ''
code = 4000
# 调用默认的异常处理函数
response = exception_handler(ex, context)
if isinstance(ex, AuthenticationFailed):
code = 401
code_type = response.data.get('detail').code
if code_type == 'no_active_account':
code=400
return ErrorResponse(status=HTTP_401_UNAUTHORIZED)
msg = ex.detail
elif isinstance(ex,Http404):
code = 400

View File

@@ -20,7 +20,7 @@ from django_filters.rest_framework import DjangoFilterBackend
from django_filters.utils import get_model_field
from rest_framework.filters import BaseFilterBackend
from dvadmin.system.models import Dept, ApiWhiteList
from dvadmin.system.models import Dept, ApiWhiteList, RoleMenuButtonPermission
def get_dept(dept_id: int, dept_all_list=None, dept_list=None):
@@ -105,11 +105,21 @@ class DataLevelPermissionsFilter(BaseFilterBackend):
# (2, "本部门数据权限"),
# (3, "全部数据权限"),
# (4, "自定数据权限")
role_list = request.user.role.filter(status=1).values("admin", "data_range")
replace_str = re.compile('\d')
re_api = replace_str.sub('{id}', api)
role_id_list = request.user.role.values_list('id', flat=True)
role_permission_list=RoleMenuButtonPermission.objects.filter(
role__in=role_id_list,
role__status=1,
menu_button__api=re_api,
menu_button__method=method).values(
'data_range',
role_admin=F('role__admin')
)
dataScope_list = [] # 权限范围列表
for ele in role_list:
for ele in role_permission_list:
# 判断用户是否为超级管理员角色/如果拥有[全部数据权限]则返回所有数据
if 3 == ele.get("data_range") or ele.get("admin") == True:
if 3 == ele.get("data_range") or ele.get("role_admin") == True:
return queryset
dataScope_list.append(ele.get("data_range"))
dataScope_list = list(set(dataScope_list))

View File

@@ -20,12 +20,10 @@ class SuccessResponse(Response):
content_type=None,page=1,limit=1,total=1):
std_data = {
"code": 2000,
"data": {
"page": page,
"limit": limit,
"total": total,
"data": data
},
"page": page,
"limit": limit,
"total": total,
"data": data,
"msg": msg
}
super().__init__(std_data, status, template_name, headers, exception, content_type)

View File

@@ -10,7 +10,7 @@
from collections import OrderedDict
from django.core import paginator
from django.core.paginator import Paginator as DjangoPaginator
from django.core.paginator import Paginator as DjangoPaginator, InvalidPage
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
@@ -21,23 +21,65 @@ class CustomPagination(PageNumberPagination):
max_page_size = 999
django_paginator_class = DjangoPaginator
def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
empty = True
page_size = self.get_page_size(request)
if not page_size:
return None
paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages
try:
self.page = paginator.page(page_number)
except InvalidPage as exc:
# msg = self.invalid_page_message.format(
# page_number=page_number, message=str(exc)
# )
# raise NotFound(msg)
empty = False
pass
if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
self.request = request
if not empty:
self.page = []
return list(self.page)
def get_paginated_response(self, data):
code = 2000
msg = 'success'
res = {
"page": int(self.get_page_number(self.request, paginator)) or 1,
"total": self.page.paginator.count,
"limit": int(self.get_page_size(self.request)) or 10,
"data": data
}
page =int(self.get_page_number(self.request, paginator)) or 1
total=self.page.paginator.count if self.page else 0
limit= int(self.get_page_size(self.request)) or 10
is_next= self.page.has_next()
is_previous= self.page.has_previous()
data=data
if not data:
code = 2000
msg = "暂无数据"
res['data'] = []
data = []
return Response(OrderedDict([
('code', code),
('msg', msg),
# ('total',self.page.paginator.count),
('data', res),
('page', page),
('limit', limit),
('total',total),
('is_next',is_next),
('is_previous', is_previous),
('data', data)
]))

View File

@@ -12,7 +12,7 @@ from django.contrib.auth.models import AnonymousUser
from django.db.models import F
from rest_framework.permissions import BasePermission
from dvadmin.system.models import ApiWhiteList
from dvadmin.system.models import ApiWhiteList, RoleMenuButtonPermission
def ValidationApi(reqApi, validApi):
@@ -81,7 +81,8 @@ class CustomPermission(BasePermission):
# ********#
if not hasattr(request.user, "role"):
return False
userApiList = request.user.role.values('permission__api', 'permission__method') # 获取当前用户的角色拥有的所有接口
role_id_list = request.user.role.values_list('id',flat=True)
userApiList = RoleMenuButtonPermission.objects.filter(role__in=role_id_list).values(permission__api=F('menu_button__api'), permission__method=F('menu_button__method')) # 获取当前用户的角色拥有的所有接口
ApiList = [
str(item.get('permission__api').replace('{id}', '([a-zA-Z0-9-]+)')) + ":" + str(
item.get('permission__method')) + '$' for item in userApiList if item.get('permission__api')]

View File

@@ -20,7 +20,8 @@ from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailRe
from dvadmin.utils.permission import CustomPermission
from django_restql.mixins import QueryArgumentsMixin
class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixin,QueryArgumentsMixin):
class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMixin, QueryArgumentsMixin):
"""
自定义的ModelViewSet:
统一标准的返回格式;新增,查询,修改可使用不同序列化器
@@ -36,13 +37,13 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
update_serializer_class = None
filter_fields = '__all__'
search_fields = ()
extra_filter_backends = [DataLevelPermissionsFilter]
extra_filter_class = [DataLevelPermissionsFilter]
permission_classes = [CustomPermission]
import_field_dict = {}
export_field_label = {}
def filter_queryset(self, queryset):
for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])):
for backend in set(set(self.filter_backends) | set(self.extra_filter_class or [])):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
@@ -51,7 +52,6 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
return self.values_queryset
return super().get_queryset()
def get_serializer_class(self):
action_serializer_name = f"{self.action}_serializer_class"
action_serializer_class = getattr(self, action_serializer_name, None)
@@ -107,17 +107,17 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
instance.delete()
return DetailResponse(data=[], msg="删除成功")
keys = openapi.Schema(description='主键列表', type=openapi.TYPE_ARRAY, items=openapi.TYPE_STRING)
keys = openapi.Schema(description='主键列表',type=openapi.TYPE_ARRAY,items=openapi.TYPE_STRING)
@swagger_auto_schema(request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['keys'],
properties={'keys': keys}
), operation_summary='批量删除')
@action(methods=['delete'],detail=False)
def multiple_delete(self,request,*args,**kwargs):
@action(methods=['delete'], detail=False)
def multiple_delete(self, request, *args, **kwargs):
request_data = request.data
keys = request_data.get('keys',None)
keys = request_data.get('keys', None)
if keys:
self.get_queryset().filter(id__in=keys).delete()
return SuccessResponse(data=[], msg="删除成功")