Chau Loi
Chau Loi

Reputation: 1225

Django - How to logging by decorator?

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

Answers (1)

user2390182
user2390182

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

Related Questions