diff --git a/backend/.gitignore b/backend/.gitignore index 7119be0..a09ea3d 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -91,7 +91,7 @@ ENV/ **/migrations/*.py !**/migrations/__init__.py *.pyc -conf/ +conf/* !conf/env.example.py db.sqlite3 media/ diff --git a/backend/application/settings.py b/backend/application/settings.py index 17453c8..f2cca95 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -55,10 +55,10 @@ INSTALLED_APPS = [ "rest_framework", "django_filters", "corsheaders", # 注册跨域app - "dvadmin.system", "drf_yasg", "captcha", 'channels', + *locals().get("CUSTOM_APPS", []), # 所有项目里写的app需要在env.py文件里的CUSTOM_APPS中 ] MIDDLEWARE = [ diff --git a/backend/conf/env.example.py b/backend/conf/env.example.py new file mode 100644 index 0000000..ee2e518 --- /dev/null +++ b/backend/conf/env.example.py @@ -0,0 +1,10 @@ +DATABASE_ENGINE = 'django.db.backends.mysql' +DATABASE_NAME = 'dvadmin3' +DATABASE_USER = 'root' +DATABASE_PASSWORD = 'root' +DATABASE_HOST = '127.0.0.1' +DATABASE_PORT = '3306' +ALLOWED_HOSTS = ['*'] +CUSTOM_APPS = [ + "dvadmin.system", +] diff --git a/backend/dvadmin/system/fixtures/initSerializer.py b/backend/dvadmin/system/fixtures/initSerializer.py index 210e4a7..fc701bc 100644 --- a/backend/dvadmin/system/fixtures/initSerializer.py +++ b/backend/dvadmin/system/fixtures/initSerializer.py @@ -188,7 +188,7 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer): class Meta: model = RoleMenuButtonPermission - fields = ['role_key', 'menu_button_value','data_range','dept','creator', 'dept_belong_id'] + fields = ['role_key', 'menu_button_value', 'data_range', 'dept', 'creator', 'dept_belong_id'] read_only_fields = ["id"] extra_kwargs = { 'role': {'required': False}, diff --git a/backend/dvadmin/system/fixtures/init_menu.json b/backend/dvadmin/system/fixtures/init_menu.json index 2ad9a84..9d514fe 100644 --- a/backend/dvadmin/system/fixtures/init_menu.json +++ b/backend/dvadmin/system/fixtures/init_menu.json @@ -11,7 +11,6 @@ "status": true, "cache": false, "visible": true, - "parent": null, "children": [ { "name": "菜单管理", @@ -25,7 +24,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -57,6 +55,30 @@ "value": "menu:Delete", "api": "/api/system/menu/{id}/", "method": 3 + }, + { + "name": "查询所有", + "value": "menu:SearchAll", + "api": "/api/system/menu/get_all_menu/", + "method": 0 + }, + { + "name": "路由", + "value": "menu:router", + "api": "/api/system/menu/web_router/", + "method": 0 + }, + { + "name": "上移", + "value": "menu:MoveUp", + "api": "/api/system/menu/mode_up/", + "method": 1 + }, + { + "name": "下移", + "value": "menu:MoveDown", + "api": "/api/system/menu/mode_down/", + "method": 1 } ] }, @@ -72,7 +94,6 @@ "status": true, "cache": false, "visible": false, - "parent": 41, "children": [], "menu_button": [ { @@ -113,7 +134,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -145,6 +165,36 @@ "value": "dept:Delete", "api": "/api/system/dept/{id}/", "method": 3 + }, + { + "name": "查询所有", + "value": "dept:SearchAll", + "api": "/api/system/dept/all_dept/", + "method": 0 + }, + { + "name": "懒加载查询所有", + "value": "dept:LazySearchAll", + "api": "/api/system/dept/dept_lazy_tree/", + "method": 0 + }, + { + "name": "上移", + "value": "dept:MoveUp", + "api": "/api/system/dept/mode_up/", + "method": 1 + }, + { + "name": "下移", + "value": "dept:MoveDown", + "api": "/api/system/dept/mode_down/", + "method": 1 + }, + { + "name": "头信息", + "value": "dept:HeaderInfo", + "api": "/api/system/dept/dept_info/", + "method": 0 } ] }, @@ -160,7 +210,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -201,6 +250,64 @@ } ] }, + { + "name": "列管理", + "icon": "iconfont icon-bolangneng", + "sort": 5, + "is_link": false, + "is_catalog": false, + "web_path": "/columns", + "component": "system/columns/index", + "component_name": "columns", + "status": true, + "cache": false, + "visible": true, + "children": [], + "menu_button": [ + { + "name": "查询", + "value": "column:Search", + "api": "/api/system/column/", + "method": 0 + }, + { + "name": "详情", + "value": "column:Retrieve", + "api": "/api/system/column/{id}/", + "method": 0 + }, + { + "name": "新增", + "value": "column:Create", + "api": "/api/system/column/", + "method": 1 + }, + { + "name": "编辑", + "value": "column:Update", + "api": "/api/system/column/{id}/", + "method": 2 + }, + { + "name": "删除", + "value": "column:Delete", + "api": "/api/system/column/{id}/", + "method": 3 + }, + { + "name": "所有模型表", + "value": "column:AllModel", + "api": "/api/system/column/get_models/", + "method": 0 + }, + { + "name": "自动匹配所有字段", + "value": "column:AutoMatch", + "api": "/api/system/column/auto_match_fields/", + "method": 1 + } + ] + }, { "name": "用户管理", "icon": "iconfont icon-icon-", @@ -213,7 +320,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -284,7 +390,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -331,7 +436,6 @@ "status": true, "cache": false, "visible": true, - "parent": 41, "children": [], "menu_button": [ { @@ -381,7 +485,6 @@ "status": true, "cache": false, "visible": true, - "parent": null, "children": [ { "name": "系统配置", @@ -395,7 +498,6 @@ "status": true, "cache": false, "visible": true, - "parent": 49, "children": [], "menu_button": [ { @@ -442,7 +544,6 @@ "status": true, "cache": false, "visible": true, - "parent": 49, "children": [], "menu_button": [ { @@ -489,7 +590,6 @@ "status": true, "cache": false, "visible": true, - "parent": 49, "children": [], "menu_button": [ { @@ -536,7 +636,6 @@ "status": true, "cache": false, "visible": true, - "parent": 49, "children": [], "menu_button": [ { @@ -580,7 +679,6 @@ "status": true, "cache": false, "visible": true, - "parent": null, "children": [ { "name": "登录日志", @@ -594,7 +692,6 @@ "status": true, "cache": false, "visible": true, - "parent": 54, "children": [], "menu_button": [ { @@ -623,7 +720,6 @@ "status": true, "cache": false, "visible": true, - "parent": 54, "children": [], "menu_button": [ { diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 146ba0e..450a79c 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -5,12 +5,7 @@ from django.contrib.auth.models import AbstractUser, UserManager from django.db import models from django.core.exceptions import ObjectDoesNotExist, ValidationError from application import dispatch -from dvadmin.utils.models import CoreModel, table_prefix - -STATUS_CHOICES = ( - (0, "禁用"), - (1, "启用"), -) +from dvadmin.utils.models import CoreModel, table_prefix, get_custom_app_models class Role(CoreModel): @@ -107,8 +102,7 @@ class Post(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="联系电话") @@ -186,6 +180,23 @@ class Menu(CoreModel): ordering = ("sort",) +class Columns(CoreModel): + role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False) + app = models.CharField(max_length=64, verbose_name='应用名') + model = models.CharField(max_length=64, verbose_name='表名') + field_name = models.CharField(max_length=64, verbose_name='模型表字段名') + title = models.CharField(max_length=64, verbose_name='字段显示名') + is_query = models.BooleanField(default=1, verbose_name='是否可查询') + is_create = models.BooleanField(default=1, verbose_name='是否可创建') + is_update = models.BooleanField(default=1, verbose_name='是否可更新') + + class Meta: + db_table = table_prefix + "system_columns" + verbose_name = "列权限表" + verbose_name_plural = verbose_name + ordering = ("id",) + + class MenuButton(CoreModel): menu = models.ForeignKey( to="Menu", @@ -289,7 +300,7 @@ 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", @@ -374,7 +385,7 @@ class FileList(CoreModel): if not self.size: self.size = self.url.size if not self.file_url: - url = media_file_name(self,self.name) + url = media_file_name(self, self.name) self.file_url = f'media/{url}' super(FileList, self).save(*args, **kwargs) diff --git a/backend/dvadmin/system/urls.py b/backend/dvadmin/system/urls.py index 0d03cf2..4e11c04 100644 --- a/backend/dvadmin/system/urls.py +++ b/backend/dvadmin/system/urls.py @@ -16,6 +16,7 @@ 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 +from dvadmin.system.views.column import ColumnViewSet system_url = routers.SimpleRouter() system_url.register(r'menu', MenuViewSet) @@ -32,6 +33,7 @@ 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) +system_url.register(r'column', ColumnViewSet) urlpatterns = [ diff --git a/backend/dvadmin/system/views/column.py b/backend/dvadmin/system/views/column.py new file mode 100644 index 0000000..18da1ce --- /dev/null +++ b/backend/dvadmin/system/views/column.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +from rest_framework import serializers +from rest_framework.decorators import action +from rest_framework.permissions import IsAuthenticated + +from dvadmin.system.models import Columns, Role +from dvadmin.utils.models import get_custom_app_models +from dvadmin.utils.viewset import CustomModelViewSet +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse + + +class ColumnSerializer(CustomModelSerializer): + """ + 列权限序列化器 + """ + + class Meta: + model = Columns + fields = '__all__' + read_only_fields = ['id'] + + +class ColumnViewSet(CustomModelViewSet): + """ + 列权限视图集 + """ + queryset = Columns.objects.all() + serializer_class = ColumnSerializer + + def list(self, request, *args, **kwargs): + role_id = request.query_params.get('role') + app_name = request.query_params.get('app') + model_name = request.query_params.get('model') + if not role_id or not model_name or not app_name: + return SuccessResponse([]) + queryset = self.filter_queryset(self.get_queryset().filter(role_id=role_id, model=model_name, app=app_name)) + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.get_serializer(page, many=True, request=request) + return self.get_paginated_response(serializer.data) + serializer = self.get_serializer(queryset, many=True, request=request) + return SuccessResponse(data=serializer.data, msg="获取成功") + + def create(self, request, *args, **kwargs): + payload = request.data + if not Role.objects.filter(pk=payload.get('role')).exists(): + return ErrorResponse(msg='角色不存在') + model = None + for app in get_custom_app_models(): + equal = False + for model in app: + if payload.get('model') == model['model']: + equal = True + model = model + break + if equal: + break + else: + return ErrorResponse(msg='模型表不存在') + if Columns.objects.filter(app=model['app'], model=model['model'], field_name=payload.get('field_name')).exists(): + return ErrorResponse(msg='‘%s’ 字段权限已有,不可重复创建' % payload.get('title')) + serializer = self.get_serializer(data=request.data, request=request) + serializer.is_valid(raise_exception=True) + self.perform_create(serializer) + return DetailResponse(data=serializer.data, msg="新增成功") + + @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) + def get_models(self, request): + """获取所有项目app下的model""" + res = [] + for app in get_custom_app_models(): + for model in app: + res.append({ + 'app': model['app'], + 'title': model['verbose'], + 'key': model['model'] + }) + return DetailResponse(res) + + @action(methods=['POST'], detail=False, permission_classes=[IsAuthenticated]) + def auto_match_fields(self, request): + """自动匹配已有的字段""" + role_id = request.data.get('role') + app_name = request.data.get('app') + model_name = request.data.get('model') + if not role_id or not model_name or not app_name: + return DetailResponse([], msg='无操作') + for model in get_custom_app_models(app_name): + if model['model'] != model_name: + continue + for field in model['fields']: + if Columns.objects.filter( + role_id=role_id, app=app_name, model=model_name, field_name=field['name'] + ).exists(): + continue + data = { + 'role': role_id, + 'app': app_name, + 'model': model_name, + 'field_name': field['name'], + 'title': str(field['title']), + } + serializer = self.get_serializer(data=data, request=request) + serializer.is_valid(raise_exception=True) + serializer.save() + return SuccessResponse(msg='匹配成功') diff --git a/backend/dvadmin/system/views/dept.py b/backend/dvadmin/system/views/dept.py index 9eaa023..c4681fe 100644 --- a/backend/dvadmin/system/views/dept.py +++ b/backend/dvadmin/system/views/dept.py @@ -171,7 +171,6 @@ class DeptViewSet(CustomModelViewSet): previous_menu.sort, dept.sort = dept.sort, previous_menu.sort previous_menu.save() dept.save() - return SuccessResponse(data=[], msg="上移成功") @action(methods=['POST'], detail=False, permission_classes=[IsAuthenticated]) @@ -187,7 +186,6 @@ class DeptViewSet(CustomModelViewSet): next_menu.sort, dept.sort = dept.sort, next_menu.sort next_menu.save() dept.save() - return SuccessResponse(data=[], msg="下移成功") @action(methods=['GET'], detail=False, permission_classes=[]) diff --git a/backend/dvadmin/system/views/menu.py b/backend/dvadmin/system/views/menu.py index 63077e5..633fa72 100644 --- a/backend/dvadmin/system/views/menu.py +++ b/backend/dvadmin/system/views/menu.py @@ -10,6 +10,7 @@ from rest_framework import serializers from rest_framework.decorators import action from dvadmin.system.models import Menu, RoleMenuPermission +from dvadmin.system.views.menu_button import MenuButtonSerializer from dvadmin.utils.json_response import SuccessResponse, ErrorResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet @@ -23,7 +24,8 @@ class MenuSerializer(CustomModelSerializer): hasChild = serializers.SerializerMethodField() def get_menuPermission(self, instance): - queryset = instance.menuPermission.order_by('-name').values_list('name', flat=True) + queryset = instance.menuPermission.order_by('-name').values('id', 'name', 'value') + # MenuButtonSerializer(instance.menuPermission.all(), many=True) if queryset: return queryset else: @@ -47,6 +49,11 @@ class MenuCreateSerializer(CustomModelSerializer): """ name = serializers.CharField(required=False) + def create(self, validated_data): + last_sort = Menu.objects.filter(parent_id=validated_data.get('parent', None)).order_by('-sort').first().sort + validated_data['sort'] = last_sort + 1 + return super().create(validated_data) + class Meta: model = Menu fields = "__all__" @@ -148,7 +155,6 @@ class MenuViewSet(CustomModelViewSet): previous_menu.sort, menu.sort = menu.sort, previous_menu.sort previous_menu.save() menu.save() - return SuccessResponse(data=[], msg="上移成功") @action(methods=['POST'], detail=False, permission_classes=[]) @@ -164,5 +170,4 @@ class MenuViewSet(CustomModelViewSet): next_menu.sort, menu.sort = menu.sort, next_menu.sort next_menu.save() menu.save() - return SuccessResponse(data=[], msg="下移成功") diff --git a/backend/dvadmin/system/views/role.py b/backend/dvadmin/system/views/role.py index 0af5dcb..ca655f8 100644 --- a/backend/dvadmin/system/views/role.py +++ b/backend/dvadmin/system/views/role.py @@ -32,9 +32,6 @@ class RoleSerializer(CustomModelSerializer): read_only_fields = ["id"] - - - class RoleCreateUpdateSerializer(CustomModelSerializer): """ 角色管理 创建/更新时的列化器 @@ -61,7 +58,7 @@ class RoleCreateUpdateSerializer(CustomModelSerializer): fields = '__all__' -class MenuPermissonSerializer(CustomModelSerializer): +class MenuPermissionSerializer(CustomModelSerializer): """ 菜单的按钮权限 """ @@ -72,9 +69,9 @@ class MenuPermissonSerializer(CustomModelSerializer): if is_superuser: queryset = MenuButton.objects.filter(menu__id=instance.id) else: - menu_permission_id_list = self.request.user.role.values_list('permission',flat=True) - queryset = MenuButton.objects.filter(id__in=menu_permission_id_list,menu__id=instance.id) - serializer = MenuButtonSerializer(queryset,many=True, read_only=True) + menu_permission_id_list = self.request.user.role.values_list('permission', flat=True) + queryset = MenuButton.objects.filter(id__in=menu_permission_id_list, menu__id=instance.id) + serializer = MenuButtonSerializer(queryset, many=True, read_only=True) return serializer.data class Meta: @@ -82,7 +79,7 @@ class MenuPermissonSerializer(CustomModelSerializer): fields = ['id', 'parent', 'name', 'menuPermission'] -class RoleViewSet(CustomModelViewSet,FastCrudMixin): +class RoleViewSet(CustomModelViewSet, FastCrudMixin): """ 角色管理接口 list:查询 diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 083ad31..20a7892 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -12,6 +12,7 @@ from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission +from dvadmin.system.views.menu import MenuSerializer from dvadmin.utils.json_response import DetailResponse, ErrorResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet @@ -37,12 +38,13 @@ class RoleMenuButtonPermissionInitSerializer(CustomModelSerializer): fields = "__all__" read_only_fields = ["id"] + class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer): """ 初始化菜单按钮-序列化器 """ menu_button__name = serializers.CharField(source='menu_button.name', read_only=True) - menu_button__value= serializers.CharField(source='menu_button.value', read_only=True) + menu_button__value = serializers.CharField(source='menu_button.value', read_only=True) class Meta: model = RoleMenuButtonPermission @@ -72,22 +74,36 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): is_superuser = request.user.is_superuser is_admin = request.user.role.values_list('admin', flat=True) if is_superuser or True in is_admin: - queryset = Menu.objects.filter(status=1).values('name','parent','is_catalog',menu_id=F('id')) + queryset = Menu.objects.filter(status=1).values('name', 'parent', 'is_catalog', menu_id=F('id')) for item in queryset: - btn_name = MenuButton.objects.filter(menu=item['menu_id']).values_list( - 'name', flat=True) - data.append({'menu_id': item['menu_id'], 'name': item['name'], 'parent': item['parent'], - 'permission': ','.join(btn_name), 'is_catalog': item['is_catalog']}) + btn_name = MenuButton.objects.filter(menu=item['menu_id']).values_list('name', flat=True) + data.append({ + 'menu_id': item['menu_id'], + 'name': item['name'], + 'parent': item['parent'], + 'permission': btn_name, + 'is_catalog': item['is_catalog'] + }) else: - role_id = request.user.role.values_list('id',flat=True) - queryset = RoleMenuPermission.objects.filter(role__in=role_id).values('menu_id',name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog')).distinct() + role_id = request.user.role.values_list('id', flat=True) + queryset = RoleMenuPermission.objects.filter(role__in=role_id).values( + 'menu_id', name=F('menu__name'), parent=F('menu__parent'), is_catalog=F('menu__is_catalog') + ).distinct() for item in queryset: - btn_name = RoleMenuButtonPermission.objects.filter(menu_button__menu=item['menu_id']).values_list('menu_button__name',flat=True) - data.append({'menu_id':item['menu_id'], 'name':item['name'], 'parent':item['parent'],'permission':','.join(btn_name),'is_catalog':item['is_catalog']}) + btn_name = RoleMenuButtonPermission.objects.filter( + menu_button__menu=item['menu_id'] + ).values_list('menu_button__name', flat=True) + data.append({ + 'menu_id': item['menu_id'], + 'name': item['name'], + 'parent': item['parent'], + 'permission': btn_name, + 'is_catalog': item['is_catalog'] + }) return DetailResponse(data=data) @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) - def role_menu_get_button(self,request): + def role_menu_get_button(self, request): """ 当前用户角色和菜单获取可下拉选项的按钮:角色授权页面使用 :param request: @@ -100,11 +116,10 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): if is_superuser or True in is_admin: queryset = MenuButton.objects.filter(menu=menu_id).values('id', 'name') else: - role_list = request.user.role.values_list('id',flat=True) - queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__menu=menu_id).values( - btn_id=F('menu_button__id'), - name=F('menu_button__name') - ) + role_list = request.user.role.values_list('id', flat=True) + queryset = RoleMenuButtonPermission.objects.filter( + role__in=role_list, menu_button__menu=menu_id + ).values(btn_id=F('menu_button__id'), name=F('menu_button__name')) return DetailResponse(data=queryset) return ErrorResponse(msg="参数错误") @@ -142,10 +157,12 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): return DetailResponse(data=data) else: data = [] - role_list = request.user.role.values_list('id',flat=True) + role_list = request.user.role.values_list('id', flat=True) if params := request.query_params: if menu_button_id := params.get('menu_button', None): - role_queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__id=menu_button_id).values_list('data_range',flat=True) + role_queryset = RoleMenuButtonPermission.objects.filter( + role__in=role_list, menu_button__id=menu_button_id + ).values_list('data_range', flat=True) data_range_list = list(set(role_queryset)) for item in data_range_list: if item == 0: @@ -208,7 +225,7 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): 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') + queryset = Dept.objects.values('id', 'name', 'parent') else: if not params: return ErrorResponse(msg="参数错误") @@ -216,17 +233,15 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): 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( + queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list, menu_button=None).values( dept_id=F('dept__id'), name=F('dept__name'), parent=F('dept__parent') ) return DetailResponse(data=queryset) - - - @action(methods=['get'],detail=False,permission_classes=[IsAuthenticated]) - def menu_to_button(self,request): + @action(methods=['get'], detail=False, permission_classes=[IsAuthenticated]) + def menu_to_button(self, request): """ 根据所选择菜单获取已配置的按钮/接口权限:角色授权页面使用 :param request: @@ -253,7 +268,7 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): 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( + queryset = RoleMenuButtonPermission.objects.filter(role=role_id, menu_button__menu=menu_id).values( 'id', 'data_range', 'menu_button', @@ -274,7 +289,6 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): role_id = params.get('role', None) if role_id is None: return ErrorResponse(msg="未获取到参数") - queryset = RoleMenuPermission.objects.filter(role_id=role_id).values_list('menu_id',flat=True).distinct() + queryset = RoleMenuPermission.objects.filter(role_id=role_id).values_list('menu_id', flat=True).distinct() return DetailResponse(data=queryset) - diff --git a/backend/dvadmin/utils/models.py b/backend/dvadmin/utils/models.py index 2c45fa7..4ec619d 100644 --- a/backend/dvadmin/utils/models.py +++ b/backend/dvadmin/utils/models.py @@ -6,15 +6,17 @@ @Created on: 2021/5/31 031 22:08 @Remark: 公共基础model类 """ +from importlib import import_module + from django.apps import apps from django.db import models -from django.db.models import QuerySet +from django.conf import settings from application import settings table_prefix = settings.TABLE_PREFIX # 数据库表名前缀 -class SoftDeleteQuerySet(QuerySet): +class SoftDeleteQuerySet(models.QuerySet): pass @@ -106,3 +108,38 @@ def get_all_models_objects(model_name=None): if model_name: return settings.ALL_MODELS_OBJECTS[model_name] or {} return settings.ALL_MODELS_OBJECTS or {} + + +def get_model_from_app(app_name): + """获取模型里的字段""" + model_module = import_module(app_name + '.models') + filter_model = [ + getattr(model_module, item) for item in dir(model_module) + if item != 'CoreModel' and issubclass(getattr(model_module, item).__class__, models.base.ModelBase) + ] + model_list = [] + for model in filter_model: + if model.__name__ == 'AbstractUser': + continue + fields = [ + {'title': field.verbose_name, 'name': field.name, 'object': field} + for field in model._meta.fields + ] + model_list.append({ + 'app': app_name, + 'verbose': model._meta.verbose_name, + 'model': model.__name__, + 'object': model, + 'fields': fields + }) + return model_list + + +def get_custom_app_models(app_name=None): + """获取所有项目写的app里的models""" + if app_name: + return get_model_from_app(app_name) + res = [] + for app in settings.CUSTOM_APPS: + res.append(get_model_from_app(app)) + return res diff --git a/backend/dvadmin/utils/pagination.py b/backend/dvadmin/utils/pagination.py index 5e64e00..40191ef 100644 --- a/backend/dvadmin/utils/pagination.py +++ b/backend/dvadmin/utils/pagination.py @@ -40,13 +40,11 @@ class CustomPagination(PageNumberPagination): 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. @@ -58,15 +56,15 @@ class CustomPagination(PageNumberPagination): self.page = [] return list(self.page) + def get_paginated_response(self, data): code = 2000 msg = 'success' - 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 + 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() if self.page else False + is_previous = self.page.has_previous() if self.page else False if not data: code = 2000