后端-字典管理、菜单管理完成

pull/1/head
李强 2021-02-26 00:17:17 +08:00
parent e7805b6211
commit b4de7a5ff9
25 changed files with 438 additions and 74 deletions

View File

@ -1,3 +1,4 @@
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework.fields import empty from rest_framework.fields import empty
from rest_framework.request import Request from rest_framework.request import Request
@ -14,6 +15,9 @@ class CustomModelSerializer(ModelSerializer):
modifier_field_name = 'modifier' modifier_field_name = 'modifier'
# 创建人的审计字段名称, 默认creator, 继承使用时可自定义覆盖 # 创建人的审计字段名称, 默认creator, 继承使用时可自定义覆盖
creator_field_name = 'creator' creator_field_name = 'creator'
# 添加默认时间返回格式
create_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
def __init__(self, instance=None, data=empty, request=None, **kwargs): def __init__(self, instance=None, data=empty, request=None, **kwargs):
super().__init__(instance, data, **kwargs) super().__init__(instance, data, **kwargs)

View File

@ -0,0 +1,9 @@
import django_filters
from apps.permission.models import Menu
class MenuFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = Menu
fields = '__all__'

View File

@ -1,17 +1,17 @@
from django.db.models import SET_DEFAULT from django.db.models import CASCADE
from django.db.models import CharField, IntegerField, BooleanField, ForeignKey
from utils import fields from apps.op_drf.models import CoreModel
from utils.BaseModels import CoreModel
class Dept(CoreModel): class Dept(CoreModel):
name = fields.CharField(null=False, max_length=64, verbose_name="部门名称") name = CharField(max_length=64, verbose_name="部门名称")
orderNum = fields.IntegerField(verbose_name="显示排序") orderNum = IntegerField(verbose_name="显示排序")
owner = fields.CharField(max_length=32, verbose_name="负责人") owner = CharField(max_length=32, verbose_name="负责人", null=True)
phone = fields.CharField(max_length=32, verbose_name="联系电话") phone = CharField(max_length=32, verbose_name="联系电话", null=True)
email = fields.CharField(max_length=32, verbose_name="邮箱") email = CharField(max_length=32, verbose_name="邮箱", null=True)
status = fields.BooleanField(default=False, verbose_name="部门状态") status = BooleanField(default=False, verbose_name="部门状态")
parentId = fields.ForeignKey(to='Dept', on_delete=SET_DEFAULT, default=False, verbose_name="上级部门") parentId = ForeignKey(to='Dept', on_delete=CASCADE, default=False, verbose_name="上级部门")
class Meta: class Meta:
verbose_name = '部门管理' verbose_name = '部门管理'

View File

@ -1,14 +1,13 @@
from django.db.models import SET_DEFAULT from django.db.models import IntegerField, BooleanField, ForeignKey, CharField, CASCADE
from utils import fields from apps.op_drf.models import CoreModel
from utils.BaseModels import CoreModel
class Menu(CoreModel): class Menu(CoreModel):
MENU_TYPE_CHOICES = ( MENU_TYPE_CHOICES = (
(0, "目录"), ("0", "目录"),
(1, "菜单"), ("1", "菜单"),
(2, "按钮"), ("2", "按钮"),
) )
METHOD_CHOICE = ( METHOD_CHOICE = (
('GET', 'GET'), ('GET', 'GET'),
@ -20,19 +19,20 @@ class Menu(CoreModel):
('OPTIONS', 'OPTIONS'), ('OPTIONS', 'OPTIONS'),
('TRACE', 'TRACE'), ('TRACE', 'TRACE'),
) )
name = fields.CharField(null=False, max_length=64, verbose_name="菜单名称") parentId = ForeignKey(to='Menu', on_delete=CASCADE, null=True, verbose_name="上级菜单")
icon = fields.CharField(max_length=64, verbose_name="菜单图标") menuType = CharField(max_length=8,choices=MENU_TYPE_CHOICES, verbose_name="菜单类型")
orderNum = fields.IntegerField(verbose_name="显示排序") icon = CharField(max_length=64, verbose_name="菜单图标", null=True)
menuType = fields.IntegerField(choices=MENU_TYPE_CHOICES, verbose_name="菜单类型") name = CharField(max_length=64, verbose_name="菜单名称")
status = fields.BooleanField(default=False, verbose_name="菜单状态") orderNum = IntegerField(verbose_name="显示排序")
visible = fields.BooleanField(default=False, verbose_name="显示状态") isFrame = CharField(max_length=8,verbose_name="是否外链")
isFrame = fields.BooleanField(default=False, verbose_name="是否外链") web_path = CharField(max_length=128, verbose_name="前端路由地址", null=True)
web_path = fields.CharField(max_length=128, verbose_name="前端路由地址") component_path = CharField(max_length=128, verbose_name="前端组件路径", null=True)
component_path = fields.CharField(max_length=128, verbose_name="组件路径") interface_path = CharField(max_length=256, verbose_name="后端接口路径", null=True)
interface_path = fields.CharField(max_length=256, verbose_name="接口路径") interface_method = CharField(choices=METHOD_CHOICE, max_length=16, default='GET', verbose_name="接口请求方式")
interface_method = fields.CharField(choices=METHOD_CHOICE, max_length=16, verbose_name="接口请求方式") perms = CharField(max_length=256, verbose_name="权限标识", null=True)
isCache = fields.BooleanField(default=False, verbose_name="是否外链") status = CharField(max_length=8,verbose_name="菜单状态")
parentId = fields.ForeignKey(to='Menu', on_delete=SET_DEFAULT, default=False, verbose_name="上级菜单") visible = CharField(max_length=8,verbose_name="显示状态")
isCache = CharField(max_length=8, verbose_name="是否缓存")
class Meta: class Meta:
verbose_name = '菜单管理' verbose_name = '菜单管理'

View File

@ -1,13 +1,14 @@
from utils import fields from django.db.models import IntegerField, BooleanField, CharField, TextField
from utils.BaseModels import CoreModel
from apps.op_drf.models import CoreModel
class Post(CoreModel): class Post(CoreModel):
name = fields.CharField(null=False, max_length=64, verbose_name="岗位名称") name = CharField(null=False, max_length=64, verbose_name="岗位名称")
web_path = fields.CharField(max_length=32, verbose_name="岗位编码") web_path = CharField(max_length=32, verbose_name="岗位编码")
orderNum = fields.IntegerField(verbose_name="岗位顺序") orderNum = IntegerField(verbose_name="岗位顺序")
status = fields.BooleanField(default=False, verbose_name="岗位状态") status = BooleanField(default=False, verbose_name="岗位状态")
remark = fields.TextField(verbose_name="备注", help_text="备注") remark = TextField(verbose_name="备注", help_text="备注", null=True)
class Meta: class Meta:
verbose_name = '岗位管理' verbose_name = '岗位管理'

View File

@ -1,5 +1,6 @@
from utils import fields from django.db.models import IntegerField, BooleanField, CharField, TextField, ManyToManyField
from utils.BaseModels import CoreModel
from apps.op_drf.models import CoreModel
class Role(CoreModel): class Role(CoreModel):
@ -10,13 +11,15 @@ class Role(CoreModel):
(3, "本部门及以下数据权限"), (3, "本部门及以下数据权限"),
(4, "仅本人数据权限"), (4, "仅本人数据权限"),
) )
name = fields.CharField(null=False, max_length=64, verbose_name="角色名称") name = CharField(max_length=64, verbose_name="角色名称")
orderNum = fields.IntegerField(verbose_name="角色顺序") roleKey = CharField(max_length=64, verbose_name="权限字符")
status = fields.BooleanField(default=False, verbose_name="角色状态") orderNum = IntegerField(verbose_name="角色顺序")
purview = fields.IntegerField(default=0, choices=PURVIEW_CHOICES, verbose_name="权限范围") status = BooleanField(default=False, verbose_name="角色状态")
remark = fields.TextField(verbose_name="备注", help_text="备注") admin = BooleanField(default=False, verbose_name="是否为admin")
dept = fields.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门') purview = IntegerField(default=0, choices=PURVIEW_CHOICES, verbose_name="权限范围")
menu = fields.ManyToManyField(to='Menu', verbose_name='关联菜单权限') remark = TextField(verbose_name="备注", help_text="备注", null=True)
dept = ManyToManyField(to='Dept', verbose_name='数据权限-关联部门')
menu = ManyToManyField(to='Menu', verbose_name='关联菜单权限')
class Meta: class Meta:
verbose_name = '角色管理' verbose_name = '角色管理'

View File

@ -1,8 +1,9 @@
from uuid import uuid4 from uuid import uuid4
from django.contrib.auth.models import UserManager, AbstractUser from django.contrib.auth.models import UserManager, AbstractUser
from django.db.models import IntegerField, ForeignKey, CharField, TextField, ManyToManyField, CASCADE
from utils import fields from apps.op_drf.fields import CreateDateTimeField, UpdateDateTimeField
class UserProfile(AbstractUser): class UserProfile(AbstractUser):
@ -16,20 +17,20 @@ class UserProfile(AbstractUser):
(1, "前台用户"), (1, "前台用户"),
) )
objects = UserManager() objects = UserManager()
username = fields.CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号') username = CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号')
secret = fields.CharField(max_length=255, default=uuid4, verbose_name='加密秘钥') secret = CharField(max_length=255, default=uuid4, verbose_name='加密秘钥')
email = fields.CharField(max_length=255, verbose_name="邮箱") email = CharField(max_length=255, verbose_name="邮箱", null=True)
mobile = fields.CharField(max_length=255, verbose_name="电话") mobile = CharField(max_length=255, verbose_name="电话", null=True)
avatar = fields.TextField(verbose_name="头像") avatar = TextField(verbose_name="头像")
name = fields.CharField(max_length=40, verbose_name="姓名") name = CharField(max_length=40, verbose_name="姓名")
gender = fields.IntegerField(default=2, choices=GENDER_CHOICES, verbose_name="性别") gender = IntegerField(default=2, choices=GENDER_CHOICES, verbose_name="性别")
remark = fields.TextField(verbose_name="备注") remark = TextField(verbose_name="备注", null=True)
user_type = fields.IntegerField(default=2, choices=GENDER_CHOICES, verbose_name="用户类型") user_type = IntegerField(default=2, choices=GENDER_CHOICES, verbose_name="用户类型")
post = fields.ForeignKey(to='Post', verbose_name='关联岗位') post = ManyToManyField(to='Post', verbose_name='关联岗位')
role = fields.ForeignKey(to='Role', verbose_name='关联角色') role = ManyToManyField(to='Role', verbose_name='关联角色')
dept = fields.ForeignKey(to='Dept', verbose_name='归属部门') dept = ForeignKey(to='Dept', verbose_name='归属部门', on_delete=CASCADE, null=True)
create_datetime = fields.CreateDateTimeField() create_datetime = CreateDateTimeField()
update_datetime = fields.UpdateDateTimeField() update_datetime = UpdateDateTimeField()
class Meta: class Meta:
verbose_name = '用户管理' verbose_name = '用户管理'

View File

@ -1,10 +1,64 @@
from rest_framework import serializers from rest_framework import serializers
from apps.permission.models import UserProfile from apps.op_drf.serializers import CustomModelSerializer
from apps.permission.models import UserProfile, Menu, Role
class GetUserInfoSerializer(serializers.ModelSerializer): class UserProfileSerializer(CustomModelSerializer):
"""
简单用户序列化器
"""
admin = serializers.SerializerMethodField(read_only=True)
def get_admin(self, obj: UserProfile):
role_list = obj.role.all().values_list('admin', flat=True)
if True in list(set(role_list)):
return True
return False
class Meta: class Meta:
model = UserProfile model = UserProfile
fields = ( dept = 2
'username',) exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')
class MenuSerializer(CustomModelSerializer):
"""
简单菜单序列化器
"""
parentId = serializers.IntegerField(source="parentId.id", default=0)
class Meta:
model = Menu
fields = '__all__'
class CreateUpdateMenuSerializer(CustomModelSerializer):
"""
创建角色/更新时的列化器
"""
def validate(self, attrs: dict):
# name = attrs['name']
# role: Role = Role.objects.filter(name=name).first()
# if role and attrs.get('instanceId', '') != role.instanceId:
# raise APIException(message=f'角色名称[{name}]不能重复')
# if getattr(self.instance, 'is_public', False) or attrs.get('is_public', False):
# up = UserPermission(self.request.user)
# if not up.is_manager():
# raise APIException(message=f'仅Manger能创建/更新角色为公共角色')
return super().validate(attrs)
class Meta:
model = Menu
fields = "__all__"
read_only_fields = ('mtime', 'ctime', 'creator', 'modifier')
class RoleSerializer(serializers.ModelSerializer):
"""
简单角色序列化器
"""
class Meta:
model = Role
fields = '__all__'

View File

@ -0,0 +1,13 @@
from django.urls import re_path
from rest_framework.routers import DefaultRouter
from apps.permission.views import MenuModelViewSet
router = DefaultRouter()
router.register(r'menus', MenuModelViewSet)
urlpatterns = [
# re_path('menus/', MenuModelViewSet.as_view({'get': 'list'}), name='api_token_auth'),
]
urlpatterns += router.urls

View File

@ -3,17 +3,29 @@ import json
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from apps.op_drf.viewsets import CustomModelViewSet
from apps.permission.filters import MenuFilter
from apps.permission.models import Role, Menu
from apps.permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \
CreateUpdateMenuSerializer
from utils.response import SuccessResponse
class GetUserView(APIView):
class GetUserProfileView(APIView):
""" """
获取用户详细信息 获取用户详细信息
""" """
def get(self, request, format=None): def get(self, request, format=None):
# data = GetUserInfoSerializer(request.user).data user_dict = UserProfileSerializer(request.user).data
data = '{"msg":"操作成功","code":200,"permissions":["*:*:*"],"roles":["admin"],"user":{"searchValue":null,"createBy":"admin","createTime":"2020-11-20 19:29:42","updateBy":null,"updateTime":null,"remark":"管理员","params":{},"userId":1,"deptId":103,"userName":"admin","nickName":"若依","email":"ry@163.com","phonenumber":"15888888888","sex":"1","avatar":"","salt":null,"status":"0","delFlag":"0","loginIp":"127.0.0.1","loginDate":"2020-11-20T19:29:42.000+0800","dept":{"searchValue":null,"createBy":null,"createTime":null,"updateBy":null,"updateTime":null,"remark":null,"params":{},"deptId":103,"parentId":101,"ancestors":null,"deptName":"研发部门","orderNum":"1","leader":"若依","phone":null,"email":null,"status":"0","delFlag":null,"parentName":null,"children":[]},"roles":[{"searchValue":null,"createBy":null,"createTime":null,"updateBy":null,"updateTime":null,"remark":null,"params":{},"roleId":1,"roleName":"超级管理员","roleKey":"admin","roleSort":"1","dataScope":"1","menuCheckStrictly":false,"deptCheckStrictly":false,"status":"0","delFlag":null,"flag":false,"menuIds":null,"deptIds":null,"admin":true}],"roleIds":null,"postIds":null,"admin":true}}'
data = json.loads(data) return SuccessResponse({
return Response(data) 'permissions': ["*:*:*"] if not user_dict.get('admin') else Menu.objects.filter(
role__userprofile=request.user).values_list('perms', flat=True),
# 'roles': Role.objects.filter(userprofile=request.user).values_list('roleKey', flat=True),
'roles': ['admin'],
'user': user_dict
})
class GetRouters(APIView): class GetRouters(APIView):
@ -26,3 +38,39 @@ class GetRouters(APIView):
data = '{"msg":"操作成功","code":200,"data":[{"name":"System","path":"/system","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统管理","icon":"system","noCache":false},"children":[{"name":"User","path":"user","hidden":false,"component":"system/user/index","meta":{"title":"用户管理","icon":"user","noCache":false}},{"name":"Role","path":"role","hidden":false,"component":"system/role/index","meta":{"title":"角色管理","icon":"peoples","noCache":false}},{"name":"Menu","path":"menu","hidden":false,"component":"system/menu/index","meta":{"title":"菜单管理","icon":"tree-table","noCache":false}},{"name":"Dept","path":"dept","hidden":false,"component":"system/dept/index","meta":{"title":"部门管理","icon":"tree","noCache":false}},{"name":"Post","path":"post","hidden":false,"component":"system/post/index","meta":{"title":"岗位管理","icon":"post","noCache":false}},{"name":"Dict","path":"dict","hidden":false,"component":"system/dict/index","meta":{"title":"字典管理","icon":"dict","noCache":false}},{"name":"Config","path":"config","hidden":false,"component":"system/config/index","meta":{"title":"参数设置","icon":"edit","noCache":false}},{"name":"Notice","path":"notice","hidden":false,"component":"system/notice/index","meta":{"title":"通知公告","icon":"message","noCache":false}},{"name":"Log","path":"log","hidden":false,"redirect":"noRedirect","component":"ParentView","alwaysShow":true,"meta":{"title":"日志管理","icon":"log","noCache":false},"children":[{"name":"Operlog","path":"operlog","hidden":false,"component":"monitor/operlog/index","meta":{"title":"操作日志","icon":"form","noCache":false}},{"name":"Logininfor","path":"logininfor","hidden":false,"component":"monitor/logininfor/index","meta":{"title":"登录日志","icon":"logininfor","noCache":false}}]}]},{"name":"Monitor","path":"/monitor","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统监控","icon":"monitor","noCache":false},"children":[{"name":"Online","path":"online","hidden":false,"component":"monitor/online/index","meta":{"title":"在线用户","icon":"online","noCache":false}},{"name":"Job","path":"job","hidden":false,"component":"monitor/job/index","meta":{"title":"定时任务","icon":"job","noCache":false}},{"name":"Druid","path":"druid","hidden":false,"component":"monitor/druid/index","meta":{"title":"数据监控","icon":"druid","noCache":false}},{"name":"Server","path":"server","hidden":false,"component":"monitor/server/index","meta":{"title":"服务监控","icon":"server","noCache":false}},{"name":"Cache","path":"cache","hidden":false,"component":"monitor/cache/index","meta":{"title":"缓存监控","icon":"redis","noCache":false}}]},{"name":"Tool","path":"/tool","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统工具","icon":"tool","noCache":false},"children":[{"name":"Build","path":"build","hidden":false,"component":"tool/build/index","meta":{"title":"表单构建","icon":"build","noCache":false}},{"name":"Gen","path":"gen","hidden":false,"component":"tool/gen/index","meta":{"title":"代码生成","icon":"code","noCache":false}},{"name":"Swagger","path":"swagger","hidden":false,"component":"tool/swagger/index","meta":{"title":"系统接口","icon":"swagger","noCache":false}}]},{"name":"Http://ruoyi.vip","path":"http://ruoyi.vip","hidden":false,"component":"Layout","meta":{"title":"若依官网","icon":"guide","noCache":false}}]}' data = '{"msg":"操作成功","code":200,"data":[{"name":"System","path":"/system","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统管理","icon":"system","noCache":false},"children":[{"name":"User","path":"user","hidden":false,"component":"system/user/index","meta":{"title":"用户管理","icon":"user","noCache":false}},{"name":"Role","path":"role","hidden":false,"component":"system/role/index","meta":{"title":"角色管理","icon":"peoples","noCache":false}},{"name":"Menu","path":"menu","hidden":false,"component":"system/menu/index","meta":{"title":"菜单管理","icon":"tree-table","noCache":false}},{"name":"Dept","path":"dept","hidden":false,"component":"system/dept/index","meta":{"title":"部门管理","icon":"tree","noCache":false}},{"name":"Post","path":"post","hidden":false,"component":"system/post/index","meta":{"title":"岗位管理","icon":"post","noCache":false}},{"name":"Dict","path":"dict","hidden":false,"component":"system/dict/index","meta":{"title":"字典管理","icon":"dict","noCache":false}},{"name":"Config","path":"config","hidden":false,"component":"system/config/index","meta":{"title":"参数设置","icon":"edit","noCache":false}},{"name":"Notice","path":"notice","hidden":false,"component":"system/notice/index","meta":{"title":"通知公告","icon":"message","noCache":false}},{"name":"Log","path":"log","hidden":false,"redirect":"noRedirect","component":"ParentView","alwaysShow":true,"meta":{"title":"日志管理","icon":"log","noCache":false},"children":[{"name":"Operlog","path":"operlog","hidden":false,"component":"monitor/operlog/index","meta":{"title":"操作日志","icon":"form","noCache":false}},{"name":"Logininfor","path":"logininfor","hidden":false,"component":"monitor/logininfor/index","meta":{"title":"登录日志","icon":"logininfor","noCache":false}}]}]},{"name":"Monitor","path":"/monitor","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统监控","icon":"monitor","noCache":false},"children":[{"name":"Online","path":"online","hidden":false,"component":"monitor/online/index","meta":{"title":"在线用户","icon":"online","noCache":false}},{"name":"Job","path":"job","hidden":false,"component":"monitor/job/index","meta":{"title":"定时任务","icon":"job","noCache":false}},{"name":"Druid","path":"druid","hidden":false,"component":"monitor/druid/index","meta":{"title":"数据监控","icon":"druid","noCache":false}},{"name":"Server","path":"server","hidden":false,"component":"monitor/server/index","meta":{"title":"服务监控","icon":"server","noCache":false}},{"name":"Cache","path":"cache","hidden":false,"component":"monitor/cache/index","meta":{"title":"缓存监控","icon":"redis","noCache":false}}]},{"name":"Tool","path":"/tool","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统工具","icon":"tool","noCache":false},"children":[{"name":"Build","path":"build","hidden":false,"component":"tool/build/index","meta":{"title":"表单构建","icon":"build","noCache":false}},{"name":"Gen","path":"gen","hidden":false,"component":"tool/gen/index","meta":{"title":"代码生成","icon":"code","noCache":false}},{"name":"Swagger","path":"swagger","hidden":false,"component":"tool/swagger/index","meta":{"title":"系统接口","icon":"swagger","noCache":false}}]},{"name":"Http://ruoyi.vip","path":"http://ruoyi.vip","hidden":false,"component":"Layout","meta":{"title":"若依官网","icon":"guide","noCache":false}}]}'
data = json.loads(data) data = json.loads(data)
return Response(data) return Response(data)
class MenuModelViewSet(CustomModelViewSet):
"""
菜单模型的CRUD视图
"""
queryset = Menu.objects.all()
serializer_class = MenuSerializer
create_serializer_class = CreateUpdateMenuSerializer
update_serializer_class = CreateUpdateMenuSerializer
# list_serializer_class = ListRoleSerializer
# retrieve_serializer_class = DetailRoleSerializer
filter_class = MenuFilter
# update_extra_permission_classes = (IsManagerPermission,)
# destroy_extra_permission_classes = (IsManagerPermission,)
# create_extra_permission_classes = (IsManagerPermission,)
search_fields = ('name',)
ordering = 'create_datetime' # 默认排序
class RoleModelViewSet(CustomModelViewSet):
"""
角色模型的CRUD视图
"""
queryset = Role.objects.all()
serializer_class = RoleSerializer
# create_serializer_class = CreateUpdateRoleSerializer
# update_serializer_class = CreateUpdateRoleSerializer
# list_serializer_class = ListRoleSerializer
# retrieve_serializer_class = DetailRoleSerializer
# filter_class = RoleFilter
# update_extra_permission_classes = (IsManagerPermission,)
# destroy_extra_permission_classes = (IsManagerPermission,)
# create_extra_permission_classes = (IsManagerPermission,)
search_fields = ('name',)
ordering = 'create_datetime' # 默认排序

View File

View File

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class PermissionConfig(AppConfig):
name = 'system'
verbose_name = "权限管理"

View File

@ -0,0 +1,16 @@
import django_filters
from apps.system.models import DictDetails, DictData
class DictDataFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = DictData
fields = '__all__'
class DictDetailsFilter(django_filters.rest_framework.FilterSet):
dictType = django_filters.CharFilter(field_name='dict_data__dictType')
class Meta:
model = DictDetails
fields = '__all__'

View File

@ -0,0 +1,4 @@
from ..models.config_settings import ConfigSettings
from ..models.dict_data import DictData
from ..models.dict_details import DictDetails
from ..models.web_set import WebSet

View File

@ -0,0 +1,21 @@
from django.db.models import CharField, ForeignKey, BooleanField, CASCADE
from apps.op_drf.models import CoreModel
class ConfigSettings(CoreModel):
name = CharField(max_length=64, verbose_name="参数名称")
configKey = CharField(max_length=256, verbose_name="参数键名")
configValue = CharField(max_length=256, verbose_name="参数键值")
configType = BooleanField(default=False,verbose_name="是否内置")
is_status = BooleanField(default=False, verbose_name="字典状态")
sort = CharField(max_length=256, verbose_name="字典排序")
dict_data = ForeignKey(to='DictData', on_delete=CASCADE, verbose_name="关联字典")
remark = CharField(max_length=256, verbose_name="备注", null=True)
class Meta:
verbose_name = '参数设置'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.name}"

View File

@ -0,0 +1,17 @@
from django.db.models import TextField, CharField,ForeignKey
from apps.op_drf.models import CoreModel
class DictData(CoreModel):
name = CharField(max_length=64, verbose_name="字典名称")
dictType = CharField(max_length=64, verbose_name="字典类型")
status = CharField(max_length=8, verbose_name="字典状态")
remark = CharField(max_length=256,verbose_name="备注", null=True)
class Meta:
verbose_name = '字典管理'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.name}"

View File

@ -0,0 +1,20 @@
from django.db.models import CharField, ForeignKey, BooleanField, CASCADE
from apps.op_drf.models import CoreModel
class DictDetails(CoreModel):
name = CharField(max_length=64, verbose_name="字典标签")
dictValue = CharField(max_length=256, verbose_name="字典键值")
is_default = BooleanField(verbose_name="是否默认", default=False)
status = CharField(max_length=2, verbose_name="字典状态")
sort = CharField(max_length=256, verbose_name="字典排序")
dict_data = ForeignKey(to='DictData', on_delete=CASCADE, verbose_name="关联字典")
remark = CharField(max_length=256, verbose_name="备注", null=True)
class Meta:
verbose_name = '字典详情'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.name}"

View File

@ -0,0 +1,19 @@
from django.db.models import TextField, CharField
from apps.op_drf.models import CoreModel
class WebSet(CoreModel):
name = CharField(max_length=64, verbose_name="站点名称")
web_site = CharField(max_length=256, verbose_name="站点网址", null=True)
logo = CharField(max_length=256, verbose_name="网站Logo", null=True)
record_info = TextField(verbose_name="备案信息", null=True)
statistics_code = TextField(verbose_name="统计代码", null=True)
copyright_info = TextField(verbose_name="版权信息", null=True)
class Meta:
verbose_name = '站点设置'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.name}"

View File

@ -0,0 +1,47 @@
from rest_framework import serializers
from apps.op_drf.serializers import CustomModelSerializer
from apps.system.models import DictData, DictDetails
class DictDataSerializer(serializers.ModelSerializer):
"""
字典管理 简单序列化器
"""
class Meta:
model = DictData
exclude = ('description', 'creator', 'modifier')
class DictDataCreateUpdateSerializer(CustomModelSerializer):
"""
字典管理 创建/更新时的列化器
"""
class Meta:
model = DictData
fields = "__all__"
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
class DictDetailsSerializer(serializers.ModelSerializer):
"""
字典详情 简单序列化器
"""
dictType = serializers.CharField(source='dict_data.dictType', default='', read_only=True)
class Meta:
model = DictDetails
exclude = ('creator', 'modifier')
class DictDetailsCreateUpdateSerializer(CustomModelSerializer):
"""
字典详情 创建/更新时的列化器
"""
class Meta:
model = DictDetails
fields = "__all__"
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')

View File

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,12 @@
from django.urls import re_path
from rest_framework.routers import DefaultRouter
from apps.system.views import DictDataModelViewSet, DictDetailsModelViewSet, DictDetailsListModelViewSet
router = DefaultRouter()
router.register(r'dict/type', DictDataModelViewSet)
router.register(r'dict/data', DictDetailsModelViewSet)
router.register(r'dict/get/type', DictDetailsListModelViewSet)
urlpatterns = [
]
urlpatterns += router.urls

View File

@ -0,0 +1,60 @@
from rest_framework.request import Request
from apps.op_drf.viewsets import CustomModelViewSet
from apps.system.models import DictData
from apps.system.serializers import DictDataSerializer, DictDataCreateUpdateSerializer, DictDetailsSerializer, \
DictDetailsCreateUpdateSerializer
from apps.system.models import DictDetails
from apps.system.filters import DictDetailsFilter, DictDataFilter
from utils.response import SuccessResponse
class DictDataModelViewSet(CustomModelViewSet):
"""
字典管理模型的CRUD视图
"""
queryset = DictData.objects.all()
serializer_class = DictDataSerializer
create_serializer_class = DictDataCreateUpdateSerializer
# update_serializer_class = CreateUpdateRoleSerializer
# list_serializer_class = ListRoleSerializer
# retrieve_serializer_class = DetailRoleSerializer
filter_class = DictDataFilter
# update_extra_permission_classes = (IsManagerPermission,)
# destroy_extra_permission_classes = (IsManagerPermission,)
# create_extra_permission_classes = (IsManagerPermission,)
search_fields = ('name',)
ordering = 'id' # 默认排序
class DictDetailsModelViewSet(CustomModelViewSet):
"""
字典详情 模型的CRUD视图
"""
queryset = DictDetails.objects.all()
serializer_class = DictDetailsSerializer
create_serializer_class = DictDetailsCreateUpdateSerializer
# update_serializer_class = CreateUpdateRoleSerializer
# list_serializer_class = ListRoleSerializer
# retrieve_serializer_class = DetailRoleSerializer
filter_class = DictDetailsFilter
# update_extra_permission_classes = (IsManagerPermission,)
# destroy_extra_permission_classes = (IsManagerPermission,)
# create_extra_permission_classes = (IsManagerPermission,)
search_fields = ('name',)
ordering = 'sort' # 默认排序
class DictDetailsListModelViewSet(CustomModelViewSet):
"""
根据字典类型查询字典数据信息 模型的CRUD视图
"""
queryset = DictDetails.objects.filter(status=True)
serializer_class = DictDetailsSerializer
filter_class = DictDetailsFilter
search_fields = ('name',)
ordering = 'create_datetime' # 默认排序
def list(self, request: Request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
if hasattr(self, 'handle_logging'):
self.handle_logging(request, *args, **kwargs)
serializer = self.get_serializer(queryset, many=True)
return SuccessResponse(serializer.data)

View File

@ -1,11 +1,13 @@
import logging import logging
import traceback import traceback
from rest_framework import serializers, exceptions
from .response import ErrorResponse from .response import ErrorResponse
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from rest_framework.exceptions import APIException as DRFAPIException from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
class APIException(Exception): class APIException(Exception):
@ -60,12 +62,16 @@ def op_exception_handler(ex, context):
:return: :return:
""" """
msg = '' msg = ''
if isinstance(ex, DRFAPIException): code = '201'
if isinstance(ex, AuthenticationFailed):
code = 401
msg = ex.detail
elif isinstance(ex, DRFAPIException):
# set_rollback() # set_rollback()
msg = ex.detail msg = ex.detail
elif isinstance(ex, APIException): elif isinstance(ex, exceptions.APIException):
msg = ex.message msg = ex.detail
elif isinstance(ex, Exception): elif isinstance(ex, Exception):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
msg = str(ex) msg = str(ex)
return ErrorResponse(msg=msg) return ErrorResponse(msg=msg,code=code)