功能变化: 后端获取系统配置功能
parent
9597addd61
commit
8c8b38817c
|
@ -366,4 +366,7 @@ INITIALIZE_LIST = []
|
||||||
INITIALIZE_RESET_LIST = []
|
INITIALIZE_RESET_LIST = []
|
||||||
# 表前缀
|
# 表前缀
|
||||||
TABLE_PREFIX = locals().get('TABLE_PREFIX', "")
|
TABLE_PREFIX = locals().get('TABLE_PREFIX', "")
|
||||||
DEFAULT_PASSWORD = locals().get("DEFAULT_PASSWORD", "admin123456")
|
# 系统配置
|
||||||
|
SYSTEM_CONFIG = {}
|
||||||
|
# 字典配置
|
||||||
|
DICTIONARY_CONFIG = {}
|
||||||
|
|
|
@ -23,17 +23,22 @@ from rest_framework_simplejwt.views import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from application import settings
|
from application import settings
|
||||||
|
from dvadmin.system.models import SystemConfig, Dictionary
|
||||||
|
from dvadmin.system.views.dictionary import InitDictionaryViewSet
|
||||||
from dvadmin.system.views.login import (
|
from dvadmin.system.views.login import (
|
||||||
LoginView,
|
LoginView,
|
||||||
CaptchaStatusView,
|
|
||||||
CaptchaView,
|
CaptchaView,
|
||||||
ApiLogin,
|
ApiLogin,
|
||||||
LogoutView,
|
LogoutView,
|
||||||
)
|
)
|
||||||
from dvadmin.system.views.system_config import InitSettingsViewSet
|
from dvadmin.system.views.system_config import InitSettingsViewSet
|
||||||
from dvadmin.system.views.dictionary import InitDictionaryViewSet
|
|
||||||
from dvadmin.utils.swagger import CustomOpenAPISchemaGenerator
|
from dvadmin.utils.swagger import CustomOpenAPISchemaGenerator
|
||||||
|
|
||||||
|
# =========== 初始化系统配置 =================
|
||||||
|
SystemConfig.init_system_config()
|
||||||
|
Dictionary.init_dictionary()
|
||||||
|
# =========== 初始化系统配置 =================
|
||||||
|
|
||||||
schema_view = get_schema_view(
|
schema_view = get_schema_view(
|
||||||
openapi.Info(
|
openapi.Info(
|
||||||
title="Snippets API",
|
title="Snippets API",
|
||||||
|
@ -49,35 +54,36 @@ schema_view = get_schema_view(
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = (
|
urlpatterns = (
|
||||||
[
|
[
|
||||||
re_path(
|
re_path(
|
||||||
r"^swagger(?P<format>\.json|\.yaml)$",
|
r"^swagger(?P<format>\.json|\.yaml)$",
|
||||||
schema_view.without_ui(cache_timeout=0),
|
schema_view.without_ui(cache_timeout=0),
|
||||||
name="schema-json",
|
name="schema-json",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"",
|
"",
|
||||||
schema_view.with_ui("swagger", cache_timeout=0),
|
schema_view.with_ui("swagger", cache_timeout=0),
|
||||||
name="schema-swagger-ui",
|
name="schema-swagger-ui",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
r"redoc/",
|
r"redoc/",
|
||||||
schema_view.with_ui("redoc", cache_timeout=0),
|
schema_view.with_ui("redoc", cache_timeout=0),
|
||||||
name="schema-redoc",
|
name="schema-redoc",
|
||||||
),
|
),
|
||||||
path("api/system/", include("dvadmin.system.urls")),
|
path("api/system/", include("dvadmin.system.urls")),
|
||||||
path("api/login/", LoginView.as_view(), name="token_obtain_pair"),
|
path("api/login/", LoginView.as_view(), name="token_obtain_pair"),
|
||||||
path("api/logout/", LogoutView.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"),
|
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
|
||||||
re_path(
|
re_path(
|
||||||
r"^api-auth/", include("rest_framework.urls", namespace="rest_framework")
|
r"^api-auth/", include("rest_framework.urls", namespace="rest_framework")
|
||||||
),
|
),
|
||||||
path("api/captcha/", CaptchaView.as_view()),
|
path("api/captcha/", CaptchaView.as_view()),
|
||||||
path("api/captcha/status/", CaptchaStatusView.as_view()),
|
path("api/init/dictionary/", InitDictionaryViewSet.as_view()),
|
||||||
path("api/init/dictionary/", InitDictionaryViewSet.as_view()),
|
path("api/init/settings/", InitSettingsViewSet.as_view()),
|
||||||
path("api/init/settings/", InitSettingsViewSet.as_view()),
|
path("apiLogin/", ApiLogin.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)
|
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
+ static(settings.STATIC_URL, document_root=settings.STATIC_URL)
|
||||||
)
|
)
|
||||||
|
|
|
@ -37,8 +37,6 @@ TABLE_PREFIX = "sys_"
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
# 启动登录详细概略获取(通过调用api获取ip详细地址。如果是内网,关闭即可)
|
# 启动登录详细概略获取(通过调用api获取ip详细地址。如果是内网,关闭即可)
|
||||||
ENABLE_LOGIN_ANALYSIS_LOG = True
|
ENABLE_LOGIN_ANALYSIS_LOG = True
|
||||||
# 是否启用登录验证码,不需要可以设置为False,线上环境建议开启
|
|
||||||
CAPTCHA_STATE = True
|
|
||||||
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
|
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
|
||||||
LOGIN_NO_CAPTCHA_AUTH = True
|
LOGIN_NO_CAPTCHA_AUTH = True
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
@ -46,6 +44,3 @@ LOGIN_NO_CAPTCHA_AUTH = True
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["*"]
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
# 默认密码
|
|
||||||
DEFAULT_PASSWORD = "admin123456"
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -194,6 +195,35 @@ class Dictionary(CoreModel):
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
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):
|
class OperationLog(CoreModel):
|
||||||
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
|
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)
|
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)
|
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)
|
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)
|
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
||||||
FORM_ITEM_TYPE_LIST = (
|
FORM_ITEM_TYPE_LIST = (
|
||||||
(0, 'text'),
|
(0, 'text'),
|
||||||
|
@ -323,6 +353,57 @@ class SystemConfig(CoreModel):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title}"
|
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):
|
class LoginLog(CoreModel):
|
||||||
LOGIN_TYPE_CHOICES = (
|
LOGIN_TYPE_CHOICES = (
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@Created on: 2021/6/3 003 0:30
|
@Created on: 2021/6/3 003 0:30
|
||||||
@Remark: 字典管理
|
@Remark: 字典管理
|
||||||
"""
|
"""
|
||||||
from rest_framework import serializers
|
from django.conf import settings
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from dvadmin.system.models import Dictionary
|
from dvadmin.system.models import Dictionary
|
||||||
|
@ -36,26 +36,6 @@ class DictionaryCreateUpdateSerializer(CustomModelSerializer):
|
||||||
fields = '__all__'
|
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):
|
class DictionaryViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
字典管理接口
|
字典管理接口
|
||||||
|
@ -83,9 +63,7 @@ class InitDictionaryViewSet(APIView):
|
||||||
dictionary_key = self.request.query_params.get('dictionary_key')
|
dictionary_key = self.request.query_params.get('dictionary_key')
|
||||||
if dictionary_key:
|
if dictionary_key:
|
||||||
if dictionary_key == 'all':
|
if dictionary_key == 'all':
|
||||||
queryset = self.queryset.filter(status=True, is_value=False)
|
data = [ele for ele in settings.DICTIONARY_CONFIG.values()]
|
||||||
serializer = DictionaryTreeSerializer(queryset, many=True, request=request)
|
|
||||||
data = serializer.data
|
|
||||||
else:
|
else:
|
||||||
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
|
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
|
||||||
'color')
|
'color')
|
||||||
|
|
|
@ -14,7 +14,7 @@ from rest_framework.views import APIView
|
||||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||||
|
|
||||||
from application import settings
|
from django.conf import settings
|
||||||
from dvadmin.system.models import Users
|
from dvadmin.system.models import Users
|
||||||
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
|
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
|
||||||
from dvadmin.utils.request_util import save_login_log
|
from dvadmin.utils.request_util import save_login_log
|
||||||
|
@ -34,7 +34,7 @@ class CaptchaView(APIView):
|
||||||
)
|
)
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
data = {}
|
data = {}
|
||||||
if settings.CAPTCHA_STATE:
|
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
|
||||||
hashkey = CaptchaStore.generate_key()
|
hashkey = CaptchaStore.generate_key()
|
||||||
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
|
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
|
||||||
imgage = captcha_image(request, hashkey)
|
imgage = captcha_image(request, hashkey)
|
||||||
|
@ -47,15 +47,6 @@ class CaptchaView(APIView):
|
||||||
return DetailResponse(data=data)
|
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):
|
class LoginSerializer(TokenObtainPairSerializer):
|
||||||
"""
|
"""
|
||||||
登录的序列化器:
|
登录的序列化器:
|
||||||
|
@ -75,7 +66,7 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
captcha = self.initial_data.get("captcha", None)
|
captcha = self.initial_data.get("captcha", None)
|
||||||
if settings.CAPTCHA_STATE:
|
if settings.SYSTEM_CONFIG.get("base.captcha_state"):
|
||||||
if captcha is None:
|
if captcha is None:
|
||||||
raise CustomValidationError("验证码不能为空")
|
raise CustomValidationError("验证码不能为空")
|
||||||
self.image_code = CaptchaStore.objects.filter(
|
self.image_code = CaptchaStore.objects.filter(
|
||||||
|
@ -87,8 +78,8 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||||
raise CustomValidationError("验证码过期")
|
raise CustomValidationError("验证码过期")
|
||||||
else:
|
else:
|
||||||
if self.image_code and (
|
if self.image_code and (
|
||||||
self.image_code.response == captcha
|
self.image_code.response == captcha
|
||||||
or self.image_code.challenge == captcha
|
or self.image_code.challenge == captcha
|
||||||
):
|
):
|
||||||
self.image_code and self.image_code.delete()
|
self.image_code and self.image_code.delete()
|
||||||
else:
|
else:
|
||||||
|
@ -171,9 +162,9 @@ class ApiLogin(APIView):
|
||||||
username = request.data.get("username")
|
username = request.data.get("username")
|
||||||
password = request.data.get("password")
|
password = request.data.get("password")
|
||||||
if user_obj := auth.authenticate(
|
if user_obj := auth.authenticate(
|
||||||
request,
|
request,
|
||||||
username=username,
|
username=username,
|
||||||
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
|
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
|
||||||
):
|
):
|
||||||
login(request, user_obj)
|
login(request, user_obj)
|
||||||
return redirect("/")
|
return redirect("/")
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
@Remark: 系统配置
|
@Remark: 系统配置
|
||||||
"""
|
"""
|
||||||
import django_filters
|
import django_filters
|
||||||
|
from django.conf import settings
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django_filters.rest_framework import BooleanFilter
|
from django_filters.rest_framework import BooleanFilter
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from application import settings
|
|
||||||
from dvadmin.system.models import SystemConfig
|
from dvadmin.system.models import SystemConfig
|
||||||
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
|
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
|
||||||
from dvadmin.utils.models import get_all_models_objects
|
from dvadmin.utils.models import get_all_models_objects
|
||||||
|
@ -207,15 +207,4 @@ class InitSettingsViewSet(APIView):
|
||||||
permission_classes = []
|
permission_classes = []
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
data = {
|
return DetailResponse(data=settings.SYSTEM_CONFIG)
|
||||||
"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)
|
|
||||||
|
|
Loading…
Reference in New Issue