功能变化: 后端获取系统配置功能

pull/57/head
李强 2022-05-14 00:11:25 +08:00
parent 9597addd61
commit 8c8b38817c
7 changed files with 137 additions and 94 deletions

View File

@ -366,4 +366,7 @@ INITIALIZE_LIST = []
INITIALIZE_RESET_LIST = []
# 表前缀
TABLE_PREFIX = locals().get('TABLE_PREFIX', "")
DEFAULT_PASSWORD = locals().get("DEFAULT_PASSWORD", "admin123456")
# 系统配置
SYSTEM_CONFIG = {}
# 字典配置
DICTIONARY_CONFIG = {}

View File

@ -23,17 +23,22 @@ from rest_framework_simplejwt.views import (
)
from application import settings
from dvadmin.system.models import SystemConfig, Dictionary
from dvadmin.system.views.dictionary import InitDictionaryViewSet
from dvadmin.system.views.login import (
LoginView,
CaptchaStatusView,
CaptchaView,
ApiLogin,
LogoutView,
)
from dvadmin.system.views.system_config import InitSettingsViewSet
from dvadmin.system.views.dictionary import InitDictionaryViewSet
from dvadmin.utils.swagger import CustomOpenAPISchemaGenerator
# =========== 初始化系统配置 =================
SystemConfig.init_system_config()
Dictionary.init_dictionary()
# =========== 初始化系统配置 =================
schema_view = get_schema_view(
openapi.Info(
title="Snippets API",
@ -49,35 +54,36 @@ schema_view = get_schema_view(
)
urlpatterns = (
[
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
schema_view.without_ui(cache_timeout=0),
name="schema-json",
),
path(
"",
schema_view.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
path(
r"redoc/",
schema_view.with_ui("redoc", cache_timeout=0),
name="schema-redoc",
),
path("api/system/", include("dvadmin.system.urls")),
path("api/login/", LoginView.as_view(), name="token_obtain_pair"),
path("api/logout/", LogoutView.as_view(), name="token_obtain_pair"),
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
re_path(
r"^api-auth/", include("rest_framework.urls", namespace="rest_framework")
),
path("api/captcha/", CaptchaView.as_view()),
path("api/captcha/status/", CaptchaStatusView.as_view()),
path("api/init/dictionary/", InitDictionaryViewSet.as_view()),
path("api/init/settings/", InitSettingsViewSet.as_view()),
path("apiLogin/", ApiLogin.as_view()),
]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+ static(settings.STATIC_URL, document_root=settings.STATIC_URL)
[
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
schema_view.without_ui(cache_timeout=0),
name="schema-json",
),
path(
"",
schema_view.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
path(
r"redoc/",
schema_view.with_ui("redoc", cache_timeout=0),
name="schema-redoc",
),
path("api/system/", include("dvadmin.system.urls")),
path("api/login/", LoginView.as_view(), name="token_obtain_pair"),
path("api/logout/", LogoutView.as_view(), name="token_obtain_pair"),
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
re_path(
r"^api-auth/", include("rest_framework.urls", namespace="rest_framework")
),
path("api/captcha/", CaptchaView.as_view()),
path("api/init/dictionary/", InitDictionaryViewSet.as_view()),
path("api/init/settings/", InitSettingsViewSet.as_view()),
path("apiLogin/", ApiLogin.as_view()),
re_path(r'api/upgrade_center_backend/', include('dvadmin_upgrade_center.urls')),
re_path(r'api/dvadmin_upgrade_center/', include('dvadmin_upgrade_center.urls')),
]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+ static(settings.STATIC_URL, document_root=settings.STATIC_URL)
)

View File

@ -37,8 +37,6 @@ TABLE_PREFIX = "sys_"
DEBUG = True
# 启动登录详细概略获取(通过调用api获取ip详细地址。如果是内网关闭即可)
ENABLE_LOGIN_ANALYSIS_LOG = True
# 是否启用登录验证码不需要可以设置为False线上环境建议开启
CAPTCHA_STATE = True
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
LOGIN_NO_CAPTCHA_AUTH = True
# ================================================= #
@ -46,6 +44,3 @@ LOGIN_NO_CAPTCHA_AUTH = True
# ================================================= #
ALLOWED_HOSTS = ["*"]
# 默认密码
DEFAULT_PASSWORD = "admin123456"

View File

@ -1,6 +1,7 @@
import hashlib
import os
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
@ -194,6 +195,35 @@ class Dictionary(CoreModel):
verbose_name_plural = verbose_name
ordering = ('sort',)
@classmethod
def init_dictionary(cls):
queryset = cls.objects.filter(status=True, is_value=False)
data = []
for instance in queryset:
data.append({
"id": instance.id,
"value": instance.value,
"children": list(cls.objects.filter(parent=instance.id).filter(status=1).
values('label', 'value', 'type', 'color'))
})
settings.DICTIONARY_CONFIG = {ele.get("value"): ele for ele in data}
print("初始化字典配置完成")
return
@classmethod
def get_dictionary_label(cls, key, name):
"""
获取获取字典label值
:param key: 字典管理中的key
:param name: 对应字典配置的value值
:return:
"""
children = settings.DICTIONARY_CONFIG.get(key) or []
for ele in children:
if ele.get("value") == str(name):
return ele.get("label")
return ""
class OperationLog(CoreModel):
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
@ -286,7 +316,7 @@ class SystemConfig(CoreModel):
key = models.CharField(max_length=20, verbose_name="", help_text="", db_index=True)
value = models.JSONField(max_length=100, verbose_name="", help_text="", null=True, blank=True)
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
status = models.BooleanField(default=False, verbose_name="启用状态", help_text="启用状态")
status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
FORM_ITEM_TYPE_LIST = (
(0, 'text'),
@ -323,6 +353,57 @@ class SystemConfig(CoreModel):
def __str__(self):
return f"{self.title}"
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
super().save(force_insert, force_update, using, update_fields)
self.init_system_config()
@classmethod
def get_system_config(cls, name):
"""
1.只传父级的key返回全部子级{ "父级key.子级key" : "" }
2."父级key.子级key"返回子级值
:param name:
:return:
"""
key_list = name.split('.')
if len(key_list) > 2:
return ""
elif len(key_list) == 2:
parent_key = key_list[0]
children_key = key_list[1]
instance = cls.objects.filter(parent__key=parent_key, key=children_key, status=True).first()
return instance.value if instance else ""
elif len(key_list) == 1:
instance = cls.objects.filter(key=key_list[0], status=True, parent_id__isnull=True).first()
if not instance:
return ""
system_config_obj = cls.objects.filter(parent_id=instance.id, status=True).values(
'parent__key', 'key', 'value', 'form_item_type').order_by('sort')
data = {}
for system_config in system_config_obj:
data[f"{system_config.get('parent__key')}.{system_config.get('key')}"] = system_config.get(
'value') or ''
return data
return ""
@classmethod
def init_system_config(cls):
"""
初始化系统配置
:param name:
:return:
"""
data = {}
system_config_obj = SystemConfig.objects.filter(status=True, parent_id__isnull=False).values(
'parent__key', 'key', 'value', 'form_item_type').order_by('sort')
for system_config in system_config_obj:
data[f"{system_config.get('parent__key')}.{system_config.get('key')}"] = system_config.get('value') or ''
settings.SYSTEM_CONFIG = data
print("初始化系统配置完成")
return
class LoginLog(CoreModel):
LOGIN_TYPE_CHOICES = (

View File

@ -6,7 +6,7 @@
@Created on: 2021/6/3 003 0:30
@Remark: 字典管理
"""
from rest_framework import serializers
from django.conf import settings
from rest_framework.views import APIView
from dvadmin.system.models import Dictionary
@ -36,26 +36,6 @@ class DictionaryCreateUpdateSerializer(CustomModelSerializer):
fields = '__all__'
class DictionaryTreeSerializer(CustomModelSerializer):
"""
字典表的树形序列化器
"""
children = serializers.SerializerMethodField(read_only=True)
def get_children(self, instance):
queryset = Dictionary.objects.filter(parent=instance.id).filter(status=1).values('label', 'value', 'type',
'color')
if queryset:
return queryset
else:
return []
class Meta:
model = Dictionary
fields = ['id', 'value', 'children']
read_only_fields = ["id"]
class DictionaryViewSet(CustomModelViewSet):
"""
字典管理接口
@ -83,9 +63,7 @@ class InitDictionaryViewSet(APIView):
dictionary_key = self.request.query_params.get('dictionary_key')
if dictionary_key:
if dictionary_key == 'all':
queryset = self.queryset.filter(status=True, is_value=False)
serializer = DictionaryTreeSerializer(queryset, many=True, request=request)
data = serializer.data
data = [ele for ele in settings.DICTIONARY_CONFIG.values()]
else:
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
'color')

View File

@ -14,7 +14,7 @@ from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from application import settings
from django.conf import settings
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.request_util import save_login_log
@ -34,7 +34,7 @@ class CaptchaView(APIView):
)
def get(self, request):
data = {}
if settings.CAPTCHA_STATE:
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
hashkey = CaptchaStore.generate_key()
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
imgage = captcha_image(request, hashkey)
@ -47,15 +47,6 @@ class CaptchaView(APIView):
return DetailResponse(data=data)
class CaptchaStatusView(APIView):
authentication_classes = []
permission_classes = []
def get(self, request):
return DetailResponse(data={"status": settings.CAPTCHA_STATE})
class LoginSerializer(TokenObtainPairSerializer):
"""
登录的序列化器:
@ -75,7 +66,7 @@ class LoginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
captcha = self.initial_data.get("captcha", None)
if settings.CAPTCHA_STATE:
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
if captcha is None:
raise CustomValidationError("验证码不能为空")
self.image_code = CaptchaStore.objects.filter(
@ -87,8 +78,8 @@ class LoginSerializer(TokenObtainPairSerializer):
raise CustomValidationError("验证码过期")
else:
if self.image_code and (
self.image_code.response == captcha
or self.image_code.challenge == captcha
self.image_code.response == captcha
or self.image_code.challenge == captcha
):
self.image_code and self.image_code.delete()
else:
@ -171,9 +162,9 @@ class ApiLogin(APIView):
username = request.data.get("username")
password = request.data.get("password")
if user_obj := auth.authenticate(
request,
username=username,
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
request,
username=username,
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
):
login(request, user_obj)
return redirect("/")

View File

@ -7,12 +7,12 @@
@Remark: 系统配置
"""
import django_filters
from django.conf import settings
from django.db.models import Q
from django_filters.rest_framework import BooleanFilter
from rest_framework import serializers
from rest_framework.views import APIView
from application import settings
from dvadmin.system.models import SystemConfig
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
from dvadmin.utils.models import get_all_models_objects
@ -207,15 +207,4 @@ class InitSettingsViewSet(APIView):
permission_classes = []
def get(self, request):
data = {
"site_name": "企业级后台管理系统", # 网站名称
"site_logo": "", # 网站logo地址
"login_background": "", # 登录页背景图
"copyright": "2021-2022 django-vue-admin.com 版权所有", # 版权
"keep_record": "晋ICP备18005113号-3", # 备案
"help_url": "https://django-vue-admin.com", # 帮助
"privacy_url": "#", # 隐私
"clause_url": "#", # 条款
"captcha_state": settings.CAPTCHA_STATE, # 验证码
}
return DetailResponse(data=data)
return DetailResponse(data=settings.SYSTEM_CONFIG)