操作日志后端逻辑完成
parent
4cfdde7622
commit
38e09f556b
|
@ -59,7 +59,7 @@ MIDDLEWARE = [
|
|||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
# 'vadmin.op_drf.middleware.ApiLoggingMiddleware', # 用于记录API访问日志
|
||||
'vadmin.op_drf.middleware.ApiLoggingMiddleware', # 用于记录API访问日志
|
||||
]
|
||||
# 允许跨域源
|
||||
CORS_ORIGIN_ALLOW_ALL = CORS_ORIGIN_ALLOW_ALL
|
||||
|
@ -313,3 +313,7 @@ CAPTCHA_NOISE_FUNCTIONS = (
|
|||
)
|
||||
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
|
||||
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
|
||||
|
||||
API_LOG_ENABLE = True
|
||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||
API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
||||
|
|
|
@ -16,11 +16,27 @@ class ViewLogger(object):
|
|||
super().__init__()
|
||||
self.view = view
|
||||
self.request = request
|
||||
self.model = None
|
||||
self.log_prefix: str = ''
|
||||
if self.view and hasattr(self.view.get_queryset(), 'model'):
|
||||
self.model: Model = self.view.get_queryset().model
|
||||
elif self.view and hasattr(self.view.get_serializer(), 'Meta') and hasattr(self.view.get_serializer().Meta,
|
||||
'model'):
|
||||
self.model: Model = self.view.get_serializer().Meta.model
|
||||
if self.model:
|
||||
request.session['model_name'] = getattr(self.model, '_meta').verbose_name
|
||||
|
||||
def handle(self, request: Request, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def logger(self, msg):
|
||||
"""
|
||||
|
||||
:param msg:
|
||||
:return: logger
|
||||
"""
|
||||
self.request.session['request_msg'] = msg
|
||||
return logger
|
||||
|
||||
class APIViewLogger(ViewLogger):
|
||||
"""
|
||||
|
@ -36,7 +52,7 @@ class APIViewLogger(ViewLogger):
|
|||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__()
|
||||
super().__init__(view, request, *args, **kwargs)
|
||||
self.view: APIView = view
|
||||
self.request: Request = request
|
||||
self.user = request.user
|
||||
|
@ -52,12 +68,7 @@ class ModelViewLogger(APIViewLogger):
|
|||
"""
|
||||
|
||||
def __init__(self, view=None, request=None, *args, **kwargs) -> None:
|
||||
super().__init__(view, request)
|
||||
|
||||
if hasattr(self.view.get_queryset(), 'model'):
|
||||
self.model: Model = self.view.get_queryset().model
|
||||
elif hasattr(self.view.get_serializer(), 'Meta') and hasattr(self.view.get_serializer().Meta, 'model'):
|
||||
self.model: Model = self.view.get_serializer().Meta.model
|
||||
super().__init__(view, request, *args, **kwargs)
|
||||
|
||||
|
||||
class RelationshipViewLogger(APIViewLogger):
|
||||
|
@ -103,7 +114,7 @@ class CustomerRelationshipViewLogger(RelationshipViewLogger):
|
|||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
logger.info(
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]新增, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
def handle_put(self, request: Request, *args, **kwargs):
|
||||
|
@ -114,7 +125,7 @@ class CustomerRelationshipViewLogger(RelationshipViewLogger):
|
|||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
logger.info(
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]重置, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
def handle_delete(self, request: Request, *args, **kwargs):
|
||||
|
@ -125,7 +136,7 @@ class CustomerRelationshipViewLogger(RelationshipViewLogger):
|
|||
model_name = getattr(self.view.model, '_meta').verbose_name
|
||||
to_field_name = self.view.to_field_name
|
||||
to_model_name = getattr(self.view.relationship_model, '_meta').verbose_name
|
||||
logger.info(
|
||||
self.logger(
|
||||
f'{self.log_prefix}用户[username={operator}]移除, {model_name}实例[{to_field_name}={self.instanceId}]与{to_model_name}的关联关系')
|
||||
|
||||
|
||||
|
@ -144,7 +155,7 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]检索{model_name}:[{instance}]')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]检索{model_name}:[{instance}]')
|
||||
|
||||
def handle_list(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
|
@ -153,7 +164,7 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]查询{model_name}')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]查询{model_name}')
|
||||
|
||||
def handle_create(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
|
@ -162,7 +173,7 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]创建{model_name}:[{instance}]')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]创建{model_name}:[{instance}]')
|
||||
|
||||
def handle_update(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
|
@ -171,7 +182,7 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]更新{model_name}:[{instance}]')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]更新{model_name}:[{instance}]')
|
||||
|
||||
def handle_partial_update(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
|
@ -180,7 +191,7 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]部分更新{model_name}:[{instance}]')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]部分更新{model_name}:[{instance}]')
|
||||
|
||||
def handle_destroy(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
|
@ -189,4 +200,4 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
logger.info(f'{self.log_prefix}用户[username={operator}]删除{model_name}:[{instance}]')
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]删除{model_name}:[{instance}]')
|
||||
|
|
|
@ -2,70 +2,31 @@
|
|||
django中间件
|
||||
"""
|
||||
|
||||
import json
|
||||
import datetime
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from mongoengine import DynamicDocument, StringField, IntField, DictField, DateTimeField
|
||||
from rest_framework_mongoengine.serializers import DocumentSerializer
|
||||
import logging
|
||||
from ..utils.decorators import exceptionHandler
|
||||
from ..utils.request_util import get_request_ip, get_request_data, get_request_path
|
||||
from .viewsets import CustomMongoModelViewSet
|
||||
from django.conf import settings
|
||||
logger = logging.getLogger(__name__)
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
|
||||
class ApiLog(DynamicDocument):
|
||||
"""
|
||||
API访问日志的Mongo模型
|
||||
"""
|
||||
request_ip = StringField(verbose_name="request_ip", help_text="请求IP")
|
||||
request_username = StringField(verbose_name="request_username", help_text="请求username")
|
||||
request_method = StringField(verbose_name="request_method", help_text="请求方法")
|
||||
request_path = StringField(verbose_name="request_path", help_text="请求路径")
|
||||
request_body = DictField(verbose_name="request_body", help_text="请求参数")
|
||||
response_code = IntField(verbose_name="response_code", help_text="响应状态码")
|
||||
response_reason = StringField(verbose_name="response_reason", help_text="响应简述")
|
||||
access_time = DateTimeField(verbose_name="access_time", help_text="访问时间")
|
||||
|
||||
|
||||
class ApiLogSerializer(DocumentSerializer):
|
||||
"""
|
||||
API访问日志的Mongo序列化器
|
||||
"""
|
||||
class Meta:
|
||||
model = ApiLog
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ApiLogModelViewSet(CustomMongoModelViewSet):
|
||||
"""
|
||||
API访问日志的CRUD视图
|
||||
"""
|
||||
queryset = ApiLog.objects.all()
|
||||
serializer_class = ApiLogSerializer
|
||||
search_fields = ('request_ip', 'request_username', 'request_method', 'response_reason', 'source_system')
|
||||
ordering = '-access_time' # 默认排序
|
||||
from apps.vadmin.system.models import RequestLog
|
||||
from ..utils.request_util import get_request_ip, get_request_data, get_request_path, get_browser, get_os, \
|
||||
get_login_location
|
||||
|
||||
|
||||
class ApiLoggingMiddleware(MiddlewareMixin):
|
||||
"""
|
||||
用于记录API访问日志中间件
|
||||
"""
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
super().__init__(get_response)
|
||||
self.enable = op_settings.get_api_log_setting().get('enable', False)
|
||||
self.methods = op_settings.get_api_log_setting().get('methods', set())
|
||||
self.enable = settings.API_LOG_ENABLE or False
|
||||
self.methods = settings.API_LOG_METHODS or set()
|
||||
|
||||
@classmethod
|
||||
@exceptionHandler()
|
||||
def __handle_request(cls, request):
|
||||
request.request_ip = get_request_ip(request)
|
||||
request.request_data = get_request_data(request)
|
||||
request.access_time = datetime.datetime.now()
|
||||
request.request_path = get_request_path(request)
|
||||
|
||||
@classmethod
|
||||
@exceptionHandler(logger=logger)
|
||||
def __handle_response(cls, request, response):
|
||||
# request_data,request_ip由PermissionInterfaceMiddleware中间件中添加的属性
|
||||
body = getattr(request, 'request_data', {})
|
||||
|
@ -74,16 +35,20 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
|||
body['password'] = '*' * len(body['password'])
|
||||
info = {
|
||||
'request_ip': getattr(request, 'request_ip', 'unknown'),
|
||||
'request_username': request.user.username,
|
||||
'creator': request.user,
|
||||
'request_method': request.method,
|
||||
'request_path': request.path,
|
||||
'request_path': request.request_path,
|
||||
'request_body': body,
|
||||
'response_code': response.status_code,
|
||||
'response_reason': response.reason_phrase,
|
||||
'source_system': getattr(settings,'SOURCE_SYSTEM_NAME',None),
|
||||
'access_time': request.access_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'request_location': get_login_location(request),
|
||||
'request_os': get_os(request),
|
||||
'request_browser': get_browser(request),
|
||||
'request_msg': request.session.get('request_msg'),
|
||||
'status': True if response.data.get('code') in [200, 204] else False,
|
||||
'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
|
||||
'request_modular': request.session.get('model_name'),
|
||||
}
|
||||
log = ApiLog(**info)
|
||||
log = RequestLog(**info)
|
||||
log.save()
|
||||
|
||||
def process_request(self, request):
|
||||
|
|
|
@ -99,189 +99,3 @@ class CustomAPIView(APIView):
|
|||
self.permission_denied(
|
||||
request, message=getattr(permission, 'message', None)
|
||||
)
|
||||
|
||||
|
||||
class BatchModelApIView(CustomAPIView):
|
||||
"""
|
||||
模型批量CRUD通用视图
|
||||
"""
|
||||
model = None
|
||||
serializer_class = None
|
||||
POST_serializer_class = None
|
||||
PUT_serializer_class = None
|
||||
field_name = 'instanceId'
|
||||
instanceId_list_param_name = 'instanceIdList'
|
||||
instance_info_param_name = 'info'
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
if not self.request:
|
||||
return None
|
||||
serializer_class = getattr(self, f"{self.request.method}_serializer_class", None) or getattr(self,
|
||||
'serializer_class')
|
||||
serializer = serializer_class(*args, **kwargs)
|
||||
if isinstance(serializer, CustomModelSerializer):
|
||||
serializer.request = self.request
|
||||
return serializer
|
||||
|
||||
def get(self, request: Request = None, *args, **kwargs):
|
||||
data = self.get_serializer(self.model.objects.filter(**{f'{self.field_name}__in': request.data}),
|
||||
many=True).data
|
||||
return SuccessResponse(data=data)
|
||||
|
||||
def post(self, request: Request = None, *args, **kwargs):
|
||||
data = []
|
||||
for info in request.data:
|
||||
serializer = self.get_serializer(data=info)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
data.append(serializer.data)
|
||||
return SuccessResponse(data=data)
|
||||
|
||||
def put(self, request: Request = None, *args, **kwargs):
|
||||
data = []
|
||||
instanceId_list = request.data.get(self.instanceId_list_param_name, [])
|
||||
info = request.data.get(self.instance_info_param_name, {})
|
||||
for instanceId in instanceId_list:
|
||||
serializer = self.get_serializer(
|
||||
instance=self.model.objects.get(**{f'{self.field_name}': instanceId}),
|
||||
data=info,
|
||||
partial=True
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return SuccessResponse(data=instanceId_list)
|
||||
|
||||
def delete(self, request: Request = None, *args, **kwargs):
|
||||
self.model.objects.filter(**{f'{self.field_name}__in': request.data}).delete()
|
||||
return SuccessResponse(data=request.data)
|
||||
|
||||
|
||||
class ModelRelationshipAPIView(CustomAPIView):
|
||||
"""
|
||||
模型关联关系通用CRUD视图
|
||||
"""
|
||||
model = None
|
||||
through_model = None
|
||||
relationship_model = None
|
||||
|
||||
relationship_serializer = None
|
||||
field_name: str = None
|
||||
from_field_name: str = 'instanceId'
|
||||
to_field_name: str = None
|
||||
relationship_field_values = ()
|
||||
|
||||
view_logger_classes = [CustomerRelationshipViewLogger, ]
|
||||
|
||||
def get_relationship_data(self, instanceId: str):
|
||||
relationship_model_field_name = self.relationship_field_values[0]
|
||||
params = {}
|
||||
params[self.field_name] = instanceId
|
||||
business_key_dict = self.through_model.objects.filter(**params).values(
|
||||
*self.relationship_field_values).distinct()
|
||||
business_key_list = [ele[relationship_model_field_name] for ele in business_key_dict]
|
||||
|
||||
params = {}
|
||||
params[f"{self.to_field_name}__in"] = business_key_list
|
||||
queryset = self.relationship_model.objects.filter(**params)
|
||||
|
||||
data = ModelRelateUtils.model_to_dict(queryset, self.relationship_serializer, default=[])
|
||||
if 'creator' in self.relationship_field_values and 'ctime' in self.relationship_field_values:
|
||||
for _index in range(len(data)):
|
||||
ele = data[_index]
|
||||
ele['relationship_creator'] = business_key_dict[_index]['creator']
|
||||
ele['relationship_ctime'] = business_key_dict[_index]['ctime']
|
||||
return data
|
||||
|
||||
def execute_method(self, execute: str, request: Request, instanceId: str, *args, **kwargs):
|
||||
method = request.method.lower()
|
||||
fun = None
|
||||
if execute == 'before':
|
||||
fun = getattr(self, f'before_{method}', None)
|
||||
elif execute == 'handle':
|
||||
fun = getattr(self, f'handle_{method}', None)
|
||||
elif execute == 'after':
|
||||
fun = getattr(self, f'after_{method}', None)
|
||||
if fun and isinstance(fun, (FunctionType, MethodType)):
|
||||
fun(request, instanceId, *args, **kwargs)
|
||||
|
||||
def do_request(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
self.execute_method('before', request, instanceId, *args, **kwargs)
|
||||
self.execute_method('handle', request, instanceId, *args, **kwargs)
|
||||
self.execute_method('after', request, instanceId, *args, **kwargs)
|
||||
self.handle_logging(request, instanceId=instanceId, *args, **kwargs)
|
||||
data = self.get_relationship_data(instanceId)
|
||||
return SuccessResponse(data)
|
||||
|
||||
def get(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
return self.do_request(request, instanceId, *args, **kwargs)
|
||||
|
||||
def post(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
return self.do_request(request, instanceId, *args, **kwargs)
|
||||
|
||||
def put(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
return self.do_request(request, instanceId, *args, **kwargs)
|
||||
|
||||
def delete(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
return self.do_request(request, instanceId, *args, **kwargs)
|
||||
|
||||
|
||||
class ModelRelationshipView(ModelRelationshipAPIView):
|
||||
"""
|
||||
模型关联关系通用CRUD视图
|
||||
"""
|
||||
|
||||
def handle_get(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
data = self.get_relationship_data(instanceId)
|
||||
return SuccessResponse(data)
|
||||
|
||||
def handle_post(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
relationship_model_field_name = self.relationship_field_values[0]
|
||||
params = {}
|
||||
params[f"{self.to_field_name}__in"] = request.data
|
||||
queryset = self.relationship_model.objects.filter(**params)
|
||||
|
||||
exist_list = [getattr(ele, self.to_field_name) for ele in queryset]
|
||||
bulk_info = []
|
||||
for _id in exist_list:
|
||||
info = {}
|
||||
info[relationship_model_field_name] = _id
|
||||
info[self.field_name] = instanceId
|
||||
info['creator'] = request.user.username
|
||||
bulk_info.append(self.through_model(**info))
|
||||
self.through_model.objects.bulk_create(bulk_info)
|
||||
data = self.get_relationship_data(instanceId)
|
||||
return SuccessResponse(data)
|
||||
|
||||
def handle_put(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
relationship_model_field_name = self.relationship_field_values[0]
|
||||
|
||||
params1 = {}
|
||||
params1[f"{self.field_name}"] = instanceId
|
||||
params2 = {}
|
||||
params2[f"{relationship_model_field_name}__in"] = request.data
|
||||
|
||||
relationships = self.through_model.objects.filter(**params1).exclude(**params2)
|
||||
relationships.delete()
|
||||
|
||||
params = {}
|
||||
params[f"{self.field_name}"] = instanceId
|
||||
|
||||
instanceId_dict = self.through_model.objects.filter(**params).values(*self.relationship_field_values).distinct()
|
||||
instanceId_list = [ele.get(relationship_model_field_name) for ele in instanceId_dict]
|
||||
create_list = list(set(request.data).difference(set(instanceId_list)))
|
||||
for _id in create_list:
|
||||
info = {}
|
||||
info[relationship_model_field_name] = _id
|
||||
info[self.field_name] = instanceId
|
||||
info['creator'] = request.user.username
|
||||
data = self.get_relationship_data(instanceId)
|
||||
return SuccessResponse(data)
|
||||
|
||||
def handle_delete(self, request: Request, instanceId: str, *args, **kwargs):
|
||||
relationship_model_field_name = self.relationship_field_values[0]
|
||||
params = {}
|
||||
params[f"{self.field_name}"] = instanceId
|
||||
params[f"{relationship_model_field_name}__in"] = request.data
|
||||
self.through_model.objects.filter(**params).delete()
|
||||
data = self.get_relationship_data(instanceId)
|
||||
return SuccessResponse(data)
|
||||
|
|
|
@ -6,4 +6,5 @@ from ..models.save_file import SaveFile
|
|||
from ..models.message_push import MessagePush
|
||||
from ..models.message_push import MessagePushUser
|
||||
from ..models.logininfor import LoginInfor
|
||||
from ..models.request_log import RequestLog
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
from django.db.models import TextField, CharField
|
||||
|
||||
from ...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, blank=True)
|
||||
logo = CharField(max_length=256, verbose_name="网站Logo", null=True, blank=True)
|
||||
record_info = TextField(verbose_name="备案信息", null=True, blank=True)
|
||||
statistics_code = TextField(verbose_name="统计代码", null=True, blank=True)
|
||||
copyright_info = TextField(verbose_name="版权信息", null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '操作日志'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
|
@ -0,0 +1,25 @@
|
|||
from django.db.models import TextField, CharField, BooleanField
|
||||
|
||||
from ...op_drf.models import CoreModel
|
||||
|
||||
|
||||
class RequestLog(CoreModel):
|
||||
request_modular = CharField(max_length=64, verbose_name="请求模块", null=True, blank=True)
|
||||
request_path = CharField(max_length=400, verbose_name="请求地址", null=True, blank=True)
|
||||
request_body = TextField(verbose_name="请求参数", null=True, blank=True)
|
||||
request_method = CharField(max_length=64, verbose_name="请求方式", null=True, blank=True)
|
||||
request_msg = CharField(max_length=64, verbose_name="操作说明", null=True, blank=True)
|
||||
request_ip = CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True)
|
||||
request_browser = CharField(max_length=32, verbose_name="请求浏览器", null=True, blank=True)
|
||||
response_code = CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True)
|
||||
request_location = CharField(max_length=32, verbose_name="操作地点", null=True, blank=True)
|
||||
request_os = CharField(max_length=64, verbose_name="操作系统", null=True, blank=True)
|
||||
json_result = TextField(verbose_name="返回信息", null=True, blank=True)
|
||||
status = BooleanField(default=False, verbose_name="响应状态")
|
||||
|
||||
class Meta:
|
||||
verbose_name = '操作日志'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.request_msg}[{self.request_modular}]"
|
|
@ -41,3 +41,6 @@ CORS_ORIGIN_ALLOW_ALL = True
|
|||
CORS_ALLOW_CREDENTIALS = False
|
||||
# 验证码状态
|
||||
CAPTCHA_STATE = True
|
||||
# 操作日志配置
|
||||
API_LOG_ENABLE = True
|
||||
API_LOG_METHODS = ['POST', 'DELETE', 'PUT'] # 'ALL' or ['POST', 'DELETE']
|
||||
|
|
Loading…
Reference in New Issue