Reputation: 1225
I want to set up logging for every single API function by using decorator
for simplicity. But keep encountering the same error. Please help
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,
},
}
}
This is my views.py
Test if the function works or not
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__)
The below is my 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)
Got this error when running it:
TypeError at /simple_function 'NoneType' object is not callable
When I comment
out the decorator @func_detail
, it works normally
Upvotes: 0
Views: 606
Reputation: 73470
Your decorated function should either return a response or raise an exception. That being said, your decorator must return a function.
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
Upvotes: 1