class MyModelClass(CallStackMixin, models.Model) # Mixin to override save, and delete
objects = CallStackManager() # Manager which overrides the get_query_setclass CallStackMixin(object):
""" A mixin class for getting call stacks when Save() and Delete() methods are called
"""
def save(self, *args, **kwargs):
"""
Logs before save and overrides respective model API save()
"""
capture_call_stack(type(self))
return super(CallStackMixin, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
"""
Logs before delete and overrides respective model API delete()
"""
capture_call_stack(type(self))
return super(CallStackMixin, self).delete(*args, **kwargs)
class CallStackManager(Manager):
""" A Manager class which overrides the default Manager class for getting call stacks
"""
def get_query_set(self):
"""overriding the default queryset API method
"""
capture_call_stack(type(self))
return super(CallStackManager, self).get_query_set()def donottrack(*classes_not_to_be_tracked):
"""function decorator which deals with toggling call stack
Args:
classes_not_to_be_tracked: model classes where tracking is undesirable
Returns:
wrapped function
"""
@wrapt.decorator
def real_donottrack(wrapped, instance, args, kwargs): # pylint: disable=W0613
"""takes function to be decorated and returns wrapped function
Args:
function - wrapped function i.e. real_donottrack
"""
global HALT_TRACKING # pylint: disable=W0603
HALT_TRACKING.append(classes_not_to_be_tracked)
HALT_TRACKING[-1] = list(set([x for sublist in HALT_TRACKING for x in sublist]))
return_value = wrapped(*args, **kwargs)
HALT_TRACKING.pop()
return return_value
return real_donottrack