Django - 如何通过装饰器记录日志?

时间:2020-12-20 16:25:48

标签: python django logging django-rest-framework

为了简单起见,我想使用 decorator 为每个 API 函数设置日志记录。但是一直遇到同样的错误。请帮忙

settings.py

log_dir = './log'                                          #create a folder for logging
log_dir = os.path.abspath(log_dir)
    if log_dir and not os.path.exists(log_dir):
        os.mkdir(log_dir)

LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
            'short': {                                                          #for internal errors
                'format': '%(asctime)s.%(msecs)03d|%(levelname)s|%(message)s',
                'datefmt': '%Y-%m-%d %H:%M:%S',                  
            },
            'data': {                                                      #for error relate to db
                'format': '%(asctime)s.%(msecs)03d|%(message)s',
                'datefmt': '%Y-%m-%d %H:%M:%S',
            },
        },
        'handlers': {
            'file_fatal': {                                           #folder for db errors
                'level': 'CRITICAL',
                'class': 'logging.FileHandler',
                'filename': os.path.join(log_dir, 'fatal.log').replace('\\', '/'),
                'formatter': 'data',
            },
            'file_info': {                                             #folder for internal errors
                'level': 'DEBUG',                                                 
                'class': 'logging.FileHandler',
                'filename': os.path.join(log_dir, 'info.log').replace('\\', '/'),
                'formatter': 'short',
            },
        },
        'loggers': {
            'main': {
                'handlers': ['file_info'],
                'level': 'DEBUG',
                'propagate': True,
            },
        }
    }

这是我的views.py

测试函数是否有效

def func_detail(func):                            #function for the decorator
    @wraps(func)
    def func_wrapper(requests,*args, **kwargs):
        log = logging.getLogger('main')
        try: 
            response = func(requests, *args, **kwargs)
            return response
        except:
            log.debug('Exception', func.__name__)

下面是我的API

class simple_function(generics.GenericAPIView):
    @func_detail
    def get(self,requests):
        input_1 = requests.GET.get('input_1')
        input_2 = requests.GET.get('input_2')
        input_3 = requests.GET.get('input_3')
        return JsonResponse([{'aaa':111, 'bbb':222, 'ccc':333}],safe =False)

运行时出现这个错误:

<块引用>

/simple_function 'NoneType' 对象的类型错误不可调用

当我comment退出装饰器@func_detail时,它正常工作

1 个答案:

答案 0 :(得分:1)

您修饰的函数应该返回响应或引发异常。话虽如此,您的装饰器必须返回一个函数。

def func_detail(func):
    @wraps(func)
    def func_wrapper(request, *args, **kwargs):
        try: 
            response = func(request, *args, **kwargs)
            return response
        except:
            log = logging.getLogger('main')
            log.debug('Exception', func.__name__)
            raise  # reraise, otherwise your view returns None
    
    return func_wrapper  # decorator must return the new function
相关问题