Skip to content

Instantly share code, notes, and snippets.

@runekaagaard
Forked from voldmar/signals.py
Last active July 4, 2022 15:41
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save runekaagaard/2eecf0a8367959dc634b7866694daf2c to your computer and use it in GitHub Desktop.
Save runekaagaard/2eecf0a8367959dc634b7866694daf2c to your computer and use it in GitHub Desktop.
List all signals by model and signal type. Tested with Django 1.7.
# coding:utf-8
import gc
import inspect
import ctypes
from collections import defaultdict
from django.core.management.base import BaseCommand
from django.db.models.signals import *
try:
from django.dispatch.dispatcher import WEAKREF_TYPES
except ImportError:
import weakref
WEAKREF_TYPES = weakref.ReferenceType,
MSG = '{module}.{name} #{line}'
SIGNAL_NAMES = {
pre_init: 'pre_init',
post_init: 'post_init',
pre_save: 'pre_save',
post_save: 'post_save',
pre_delete: 'pre_delete',
post_delete: 'post_delete',
m2m_changed: 'm2m_changed',
pre_migrate: 'pre_migrate',
post_migrate: 'post_migrate',
pre_syncdb: 'pre_syncdb',
post_syncdb: 'post_syncdb',
}
class Command(BaseCommand):
help = 'List all signals by model and signal type'
def handle(self, *args, **options):
signals = [obj for obj in gc.get_objects() if isinstance(obj, ModelSignal)]
models = defaultdict(lambda: defaultdict(list))
for signal in signals:
signal_name = SIGNAL_NAMES.get(signal, 'unknown')
for receiver in signal.receivers:
lookup, receiver = receiver
if isinstance(receiver, WEAKREF_TYPES):
receiver = receiver()
if receiver is None:
continue
receiver_id, sender_id = lookup
model = ctypes.cast(sender_id, ctypes.py_object).value
models[model][signal_name].append(MSG.format(
name=receiver.func_name,
module=receiver.__module__,
line=inspect.getsourcelines(
receiver)[1], path=inspect.getsourcefile(receiver))
)
for key in sorted(models.keys()):
print '' + key.__module__ + "." + key.__name__, u"({})".format(
key._meta.verbose_name)
for signal_name, lines in models[key].iteritems():
print " "*4, signal_name
for line in lines:
print " "*8, line
@AlanCoding
Copy link

I find that pre_syncdb and post_syncdb are not defined. Deleting those, the rest of it works.

Django 1.11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment