功能变化: 后端获取系统配置功能
							parent
							
								
									9597addd61
								
							
						
					
					
						commit
						8c8b38817c
					
				|  | @ -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 = {} | ||||
|  |  | |||
|  | @ -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) | ||||
| ) | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -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 = ( | ||||
|  |  | |||
|  | @ -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') | ||||
|  |  | |||
|  | @ -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("/") | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 李强
						李强