【问题标题】:Django - How to logging by decorator?Django - 如何通过装饰器记录?
【发布时间】:2021-03-30 14:05:13
【问题描述】:

为了简单起见,我想使用 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' 对象的 TypeError 是不可调用的

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

【问题讨论】:

  • 您是否尝试返回 func_wrapper 函数?在func_wrapper函数中设置响应变量后,返回。
  • 效果不好
  • 哦,既然已经通过 args 接收到了 wrapper 函数中的 'requests' 参数,那如何呢?或者,试试下面@schwobaseggl 的解决方案?
  • @guten_pro 感谢您的支持,但是,删除 requests 不起作用

标签: python django logging django-rest-framework


【解决方案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

【讨论】:

  • 效果很好,tks
猜你喜欢
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
相关资源
最近更新 更多