示例#1
0
def turn_on_syncing():
    """
    Enables all of the signals for syncing entities.
    """
    post_delete.connect(delete_entity_signal_handler, dispatch_uid='delete_entity_signal_handler')
    post_save.connect(save_entity_signal_handler, dispatch_uid='save_entity_signal_handler')
    post_bulk_operation.connect(bulk_operation_signal_handler, dispatch_uid='bulk_operation_signal_handler')
def cache_purge_hook(model, func=None):
    pre_save.connect(
        partial(__pre_save_hook, model, func),
        dispatch_uid="cache_purge_hook",
        sender=model,
        weak=False,
    )
    post_save.connect(
        partial(__post_save_hook, model, func),
        dispatch_uid="cache_purge_hook",
        sender=model,
        weak=False,
    )
    pre_delete.connect(
        partial(__pre_delete_hook, model, func),
        dispatch_uid="cache_purge_hook",
        sender=model,
        weak=False,
    )
    post_delete.connect(
        partial(__post_delete_hook, model, func),
        dispatch_uid="cache_purge_hook",
        sender=model,
        weak=False,
    )
示例#3
0
 def register(self, model, monitoring_level=1, stream=False):
     if monitoring_level == 1:
         post_save.connect(mmessage_create, sender=model)
     if monitoring_level == 2:
         post_save.connect(mmessage_save, sender=model)
     post_delete.connect(mmessage_delete, sender=model)
     return
示例#4
0
 def tearDown(self):
     version_changed_signal.connect(version_changed,
                                    dispatch_uid='version_changed')
     post_save.connect(update_status, sender=Version,
                       dispatch_uid='version_update_status')
     post_delete.connect(update_status, sender=Version,
                         dispatch_uid='version_update_status')
示例#5
0
def disconnect_es_signals():

    models = get_es_indexed_models()

    for model in models:
        post_save.disconnect(es_index_instance, sender=model)
        post_delete.connect(es_delete_instance, sender=model)
示例#6
0
 def ready(self):
     from c3nav.editor.models import ChangeSet
     from c3nav.editor.signals import set_changeset_author_on_login
     post_save.connect(ChangeSet.object_changed_handler)
     post_delete.connect(ChangeSet.object_changed_handler)
     m2m_changed.connect(ChangeSet.object_changed_handler)
     user_logged_in.connect(set_changeset_author_on_login)
示例#7
0
def cache_model(model, timeout=None):
    """
    Adds utility methods to the given model to obtain
    ``ForeignKey`` instances via the cache.
    """
    if hasattr(model, 'get_cached'):
        # Already patched
        return

    def clear_cache(sender, instance, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Clears the cache for the given instance.
        """
        delete_instance(sender, instance)

    post_save.connect(clear_cache, sender=model, weak=False)
    post_delete.connect(clear_cache, sender=model, weak=False)

    @classmethod
    def get(cls, pk, using=None):  # pylint: disable=invalid-name
        """
        Returns the model for the given primary key (pk).
        """
        if pk is None:
            return None
        return get_instance(cls, pk, timeout, using)

    model.get_cached = get
 def contribute_to_class(self, cls, name):
     """
     Add each of the names and fields in the ``fields`` attribute
     to the model the relationship field is applied to, and set up
     the related item save and delete signals for calling
     ``related_items_changed``.
     """
     for field in cls._meta.many_to_many:
         if isinstance(field, self.__class__):
             e = "Multiple %s fields are not supported (%s.%s, %s.%s)" % (
                 self.__class__.__name__, cls.__name__, cls.__name__,
                 name, field.name)
             raise ImproperlyConfigured(e)
     self.related_field_name = name
     super(BaseGenericRelation, self).contribute_to_class(cls, name)
     # Not applicable to abstract classes, and in fact will break.
     if not cls._meta.abstract and not self.frozen_by_south:
         for (name_string, field) in self.fields.items():
             if "%s" in name_string:
                 name_string = name_string % name
             if not field.verbose_name:
                 field.verbose_name = self.verbose_name
             cls.add_to_class(name_string, copy(field))
         # Add a getter function to the model we can use to retrieve
         # the field/manager by type without knowing its name.
         getter_name = "get_%s_manager" % self.__class__.__name__.lower()
         cls.add_to_class(getter_name, lambda s: getattr(s, name))
         # For some unknown reason the signal won't be triggered
         # if given a sender arg, particularly when running
         # Cartridge with the field RichTextPage.keywords - so
         # instead of specifying self.rel.to as the sender, we
         # check for it inside the signal itself.
         post_save.connect(self._related_items_changed)
         post_delete.connect(self._related_items_changed)
示例#9
0
def _run_listen():
    post_save.connect(run_watchers.post_run_saved, sender=TestRun)
    post_save.connect(run_watchers.post_case_run_saved, sender=TestCaseRun,
                      dispatch_uid='tcms.testruns.models.TestCaseRun')
    post_delete.connect(run_watchers.post_case_run_deleted, sender=TestCaseRun,
                        dispatch_uid='tcms.testruns.models.TestCaseRun')
    pre_save.connect(run_watchers.pre_save_clean, sender=TestRun)
示例#10
0
    def delete(self, uid, username, commit_msg, save):
        def deletefile(sender, instance=None, **kwargs):
            # check that the instance is the right one
            fieldfile = getattr(instance, self.fieldname)
            try:
                saved_uid = fieldfile.name
            except AttributeError:
                # an instance of another class
                return
            if saved_uid != uid:
                return
            fieldfile.name = None
            setattr(instance, fieldfile.field.name, fieldfile.name)
            self.backend.del_document(instance, commit_msg, username)

            # Delete the filesize cache
            if hasattr(fieldfile, '_size'):
                del fieldfile._size
            fieldfile._committed = False

            if save:
                instance.save()

            # remove signal
            post_delete.disconnect(dispatch_uid=uid)

        post_delete.connect(deletefile, weak=False, dispatch_uid=uid)
        return force_text(uid.replace('\\', '/'))
示例#11
0
    def contribute_to_class(self, cls, name):
        setattr(cls, name, ImageSpecFileDescriptor(self, name))
        try:
            # Make sure we don't modify an inherited ImageKitMeta instance
            ik = cls.__dict__['ik']
        except KeyError:
            try:
                base = getattr(cls, '_ik')
            except AttributeError:
                ik = ImageKitMeta()
            else:
                # Inherit all the spec fields.
                ik = ImageKitMeta(base.spec_fields)
            setattr(cls, '_ik', ik)
        ik.spec_fields.append(name)

        # Connect to the signals only once for this class.
        uid = '%s.%s' % (cls.__module__, cls.__name__)
        post_init.connect(ImageSpecField._post_init_receiver, sender=cls,
                dispatch_uid=uid)
        post_save.connect(ImageSpecField._post_save_receiver, sender=cls,
                dispatch_uid=uid)
        post_delete.connect(ImageSpecField._post_delete_receiver, sender=cls,
                dispatch_uid=uid)

        # Register the field with the image_cache_backend
        try:
            self.image_cache_backend.register_field(cls, self, name)
        except AttributeError:
            pass
示例#12
0
文件: engines.py 项目: idan/djoosh
    def register(self, model_or_iterable, search_class=None, **options):
        """
        Registers the given model(s) with the given search class.

        The model(s) should be Model classes, not instances.

        If an search class isn't given, it will use ModelSearch (the default
        search options). If keyword arguments are given -- e.g., exclude --
        they'll be applied as options to the search class.

        If a model is already registered, this will raise AlreadyRegistered.
        """
        if not search_class:
            search_class = ModelSearch
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]
        for model in model_or_iterable:
            if model in self._registry:
                raise AlreadyRegistered("The model %s is already registered" % model.__name__)
            # If we got **options then dynamically construct a subclass of
            # search_class with those **options.
            if options:
                # For reasons I don't quite understand, without a __module__
                # the created class appears to "live" in the wrong place,
                # which causes issues later on.
                options["__module__"] = __name__
                search_class = type("%sSearch" % model.__name__, (search_class,), options)
            self._registry[model] = search_class(model, self)

            # Attache post_save and post_delete signals
            post_save.connect(self._registry[model].post_save_callback, sender=model)
            post_delete.connect(self._registry[model].post_delete_callback, sender=model)
示例#13
0
文件: fields.py 项目: Anlim/mezzanine
    def contribute_to_class(self, cls, name):
        """
        Add each of the names and fields in the ``fields`` attribute
        to the model the relationship field is applied to, and set up
        the related item save and delete signals for calling
        ``related_items_changed``.
        """
        for field in cls._meta.many_to_many:
            if isinstance(field, self.__class__):
                e = "Multiple %s fields are not supported (%s.%s, %s.%s)" % (
                    self.__class__.__name__, cls.__name__, cls.__name__,
                    name, field.name)
                raise ImproperlyConfigured(e)
        self.related_field_name = name
        super(BaseGenericRelation, self).contribute_to_class(cls, name)
        # Not applicable to abstract classes, and in fact will break.
        if not cls._meta.abstract:
            for (name_string, field) in self.fields.items():
                if "%s" in name_string:
                    name_string = name_string % name
                extant_fields = cls._meta._forward_fields_map
                if name_string in extant_fields:
                    continue
                if field.verbose_name is None:
                    field.verbose_name = self.verbose_name
                cls.add_to_class(name_string, copy(field))
            # Add a getter function to the model we can use to retrieve
            # the field/manager by name.
            getter_name = "get_%s_name" % self.__class__.__name__.lower()
            cls.add_to_class(getter_name, lambda self: name)

            sender = self.rel.to
            post_save.connect(self._related_items_changed, sender=sender)
            post_delete.connect(self._related_items_changed, sender=sender)
示例#14
0
def connect_cleanup_files_signals():
    connections = ConnectionHandler()
    backend = connections[DEFAULT_DB_ALIAS]

    for model in _find_models_with_filefield():
        pre_save.connect(remove_files_on_change, sender=model)
        post_delete.connect(remove_files_on_delete, sender=model)
def setup_handlers():
    try:
        for k,v in MODULES.items():
            app_label, model_name = k.split('.')
            model = get_model(app_label, model_name)
            
            # Add a tag attribute to the instance.
            if REGISTER_MODELS:
                register(model)
            
            # Setup post save and post delete handlers if model exists
            if model and AUTO_PROCESS:
                post_save.connect(save_handler, sender=model)
                post_delete.connect(delete_handler, sender=model)
            
            if MARKUP: 
                # Add a custom attribute to a model with a marked up
                # version of the field specified.
                for f in v.get('fields', []):
                    field = f.get('name', None)
                    markup = f.get('markup', True)
                    if markup and MARKUP and field:
                        from supertagging.markup import get_handler_module
                        handler = get_handler_module(f.get('markup_handler', None))
                        nfield = "%s__%s" % (field, MARKUP_FIELD_SUFFIX)
                        setattr(model, nfield, handler(model, field))
                        
    except Exception, e:
        if ST_DEBUG: raise Exception(e)
示例#16
0
    def register_model(self, bo_model):
        """
        Register a ``BackOfficeModel`` implementation class with this
        backoffice.

        :param bo_model: a ``BackOfficeModel`` implementation class
        """
        if not self.model_to_bo_model:
            self.model_to_bo_model = {}
        if not self.slug_to_bo_model:
            self.slug_to_bo_model = {}

        if not bo_model.slug in self.slug_to_bo_model:
            bo_model_instance = bo_model()
            self.slug_to_bo_model[bo_model.slug] = bo_model_instance
            self.model_to_bo_model[bo_model.model] = bo_model_instance

            # Connect signals to listen for changes to this model and their
            # ``search_index_dependencies``.
            post_save.connect(self._reindex_model_signal_handler, sender=bo_model.model)
            post_delete.connect(self._delete_index_signal_handler, sender=bo_model.model)

            for dependency in bo_model_instance.search_index_dependencies:
                self.search_index_dependency_to_dependants[dependency].append(bo_model_instance)
                post_save.connect(self._reindex_model_signal_handler, sender=dependency)
                post_delete.connect(self._reindex_model_signal_handler, sender=dependency)

        for bo_model_instance in self.model_to_bo_model.values():
            self.link_relationship(bo_model_instance)
 def register(self, model):
     post_save.connect(add_obj_to_autocompleter, sender=model,
         dispatch_uid='autocompleter.%s.add' % (model))
     pre_save.connect(remove_old_obj_from_autocompleter, sender=model,
         dispatch_uid='autocompleter.%s.remoe_old' % (model))
     post_delete.connect(remove_obj_from_autocompleter,
         sender=model, dispatch_uid='autocompleter.%s.remove' % (model))
def connect_signals(app):
    Article = app.get_model('article')

    post_save.connect(post_save_article, sender=Article,
                      dispatch_uid='blog.post_save_article')
    post_delete.connect(post_delete_article, sender=Article,
                        dispatch_uid='blog.post_delete_article')
示例#19
0
def add_signal_listeners():
    for table, properties in holonet_settings.MAPPING_MODELS.items():
        model = get_model(*table.split('.'))
        post_save.connect(mapping_change, model)
        post_delete.connect(mapping_delete, model)
        pre_save.connect(pre_save_mapping_check, model)

        # Add signal på many to many relations
        relation_list = properties.get('recipient_relations', [])
        if not isinstance(relation_list, list):
            raise HolonetConfigurationError('recipient_relations needs to be a list of strings.')

        for relation in relation_list:
            if not isinstance(relation, str):
                raise HolonetConfigurationError('Each item in recipient_relations need to be a '
                                                'string.')

            relation_field = getattr(model, relation, None)
            if relation_field is None:
                raise HolonetConfigurationError('Could not find the relation_field on the model.')

            if not isinstance(relation_field, ReverseManyDescriptor):
                raise HolonetConfigurationError('The relation field needs to be of type '
                                                'models.ManyToManyField')

            m2m_changed.connect(mapping_recipient_list_change, relation_field.through)
 def _register_model(self, model):
     if model in self._registered_models:
         return False
     post_save.connect(self.shoot_down, model)
     post_delete.connect(self.shoot_down, model)
     self._registered_models.add(model)
     return True
示例#21
0
 def _install_cacheops(self, cls):
     cls._cacheprofile = model_profile(cls)
     if cls._cacheprofile is not None and get_model_name(cls) not in _old_objs:
         # Setting up signals
         post_save.connect(self._post_save, sender=cls)
         post_delete.connect(self._post_delete, sender=cls)
         _old_objs[get_model_name(cls)] = {}
示例#22
0
def _listen():
    """ signals listen """

    # case save/delete listen for email notify
    post_save.connect(case_watchers.on_case_save, TestCase)
    post_delete.connect(case_watchers.on_case_delete, TestCase)
    pre_save.connect(case_watchers.pre_save_clean, TestCase)
示例#23
0
    def ready(self):
        if SEARCH_SIGNALS:
            from search.signals import run_post_save_search_tasks, run_post_delete_search_tasks  # noqa: F401

            search_conf = SearchConf(auto_setup=True)
            model_labels = search_conf.get_registered_models()

            logger.info('Connect post_save signals for {} models'.format(len(model_labels)))

            for label in model_labels:
                logger.info('Connecting post_save for {}'.format(label))
                post_save.connect(
                    run_post_save_search_tasks,
                    sender=label,
                    dispatch_uid='run_post_save_search_tasks::{}'.format(label)
                )
                post_delete_uid = 'run_post_delete_search_tasks::{}'.format(label)
                post_delete.connect(
                    run_post_delete_search_tasks,
                    sender=label,
                    dispatch_uid=post_delete_uid
                )

        try:
            from search.tasks import schedule_periodic_index_rebuilds
            # This should tell our rq-scheduler to run rebuild_indices periodically
            schedule_periodic_index_rebuilds()
        except Exception:
            pass
示例#24
0
    def decorator(cls):
        # Навешиваем методы и свойства
        getter = curry(_method, _get, field_name)
        setter = curry(_set_method, field_name)
        incrementer = curry(_method, _incr, field_name)

        setattr(cls, 'get_' + field_name, getter)
        setattr(cls, field_name, property(getter, setter))
        setattr(cls, 'incr_' + field_name, incrementer)

        # Навешиваем методы класса
        key_getter = curry(_key, field_name)
        cls_getter = curry(_class_method, _get, field_name)
        cls_incrementer = curry(_class_method, _incr, field_name)

        setattr(cls, 'key_for_' + field_name, classmethod(key_getter))
        setattr(cls, 'get_%s_for_pk' % field_name, classmethod(cls_getter))
        setattr(cls, 'incr_%s_for_pk' % field_name, classmethod(cls_incrementer))

        if not hasattr(cls, '_counters'):
            cls._counters = []
        cls._counters.append(field_name)

        post_delete.connect(curry(_post_delete, field_name), sender=cls,
                            weak=False, dispatch_uid=(cls, field_name))

        return cls
示例#25
0
def cache_model(model, timeout=None, aggressive_caching=False):
    if hasattr(model, 'get_cached'):
        # Already patched
        return

    def update_cache(sender, instance, *args, **kwargs):
        update_instance(sender, instance)

    def clear_cache(sender, instance, *args, **kwargs):
        delete_instance(sender, instance)

    if aggressive_caching:
        post_save.connect(update_cache, sender=model, weak=False)
    else:
        post_save.connect(clear_cache, sender=model, weak=False)

    post_delete.connect(clear_cache, sender=model, weak=False)

    @classmethod
    def get(cls, pk, using=None):
        if pk is None:
            return None
        return get_instance(cls, pk, timeout, using)

    model.get_cached = get
示例#26
0
def register_signal_handlers():
    Image = get_image_model()
    Rendition = Image.get_rendition_model()

    pre_save.connect(pre_save_image_feature_detection, sender=Image)
    post_delete.connect(post_delete_file_cleanup, sender=Image)
    post_delete.connect(post_delete_file_cleanup, sender=Rendition)
示例#27
0
 def bind_model(self, sender, **kwargs):
     #from stream_django.models import StreamActivity as DefaultStreamActivityModel
     if issubclass(sender, (Activity, )):
         post_save.connect(self.activity_created, sender=sender)
         post_delete.connect(self.activity_delete, sender=sender)
     post_save.connect(self.stream_activity_created, sender=StreamActivity)
     post_delete.connect(self.stream_activity_delete, sender=StreamActivity)
示例#28
0
def audit_model(m):
    if isinstance(m, types.StringTypes):
        model = get_model(m.split('.')[0],m.split('.')[1])
    else:
        model = m
    post_save.connect(engine.auditor_save_callback, sender=model)
    post_delete.connect(engine.auditor_delete_callback, sender=model)
    def setUp(self):
        from django.db.models.signals import post_save, post_delete
        try:
            from django.db.models.signals import post_migrate
        except ImportError:  # django <= 1.6
            from django.db.models.signals import post_syncdb as post_migrate

        from django_elasticsearch.models import es_save_callback
        from django_elasticsearch.models import es_delete_callback
        from django_elasticsearch.models import es_syncdb_callback
        try:
            from django.apps import apps
            app = apps.get_app_config('django_elasticsearch')
        except ImportError: # django 1.4
            from django.db.models import get_app
            app = get_app('django_elasticsearch')

        post_save.connect(es_save_callback)
        post_delete.connect(es_delete_callback)
        post_migrate.connect(es_syncdb_callback)
        
        if int(get_version()[2]) >= 6:
            sender = app
        else:
            sender = None
        post_migrate.send(sender=sender,
                          app_config=app,
                          app=app,  # django 1.4
                          created_models=[TestModel,],
                          verbosity=2)

        self.instance = TestModel.objects.create(username=u"1",
                                                 first_name=u"woot",
                                                 last_name=u"foo")
        self.instance.es.do_index()
示例#30
0
 def register(self, model_class, fields=None, follow=(), format=DEFAULT_SERIALIZATION_FORMAT):
     """Registers a model with this revision manager."""
     # Prevent multiple registration.
     if self.is_registered(model_class):
         raise RegistrationError, "%r has already been registered with Reversion." % model_class
     # Ensure the parent model of proxy models is registered.
     if model_class._meta.proxy and not self.is_registered(model_class._meta.parents.keys()[0]):
         raise RegistrationError, "%r is a proxy model, and its parent has not been registered with Reversion." % model_class
     # Calculate serializable model fields.
     opts = model_class._meta
     local_fields = opts.local_fields + opts.local_many_to_many
     if fields is None:
         fields = [field.name for field in local_fields]
     fields = tuple(fields)
     # Calculate serializable model file fields.
     file_fields = []
     for field in local_fields:
         if isinstance(field, models.FileField) and field.name in fields:
             field.storage = VersionFileStorageWrapper(field.storage)
             file_fields.append(field)
     file_fields = tuple(file_fields)
     # Register the generated registration information.
     follow = tuple(follow)
     registration_info = RegistrationInfo(fields, file_fields, follow, format)
     self._registry[model_class] = registration_info
     # Connect to the post save signal of the model.
     post_save.connect(self.post_save_receiver, model_class)
     post_delete.connect(self.post_delete_receiver, model_class)
示例#31
0
                =project_id,
            ).distinct().values_list("id", "emails__email")
        })

    if teams:
        actors.update({
            ("team", slug): Actor(t_id, Team)
            for t_id, slug in Team.objects.filter(
                slug__in=[o.identifier for o in teams],
                projectteam__project_id=project_id).values_list("id", "slug")
        })

    return {o: actors.get((o.type, o.identifier.lower())) for o in owners}


# Signals update the cached reads used in post_processing
post_save.connect(
    lambda instance, **kwargs: cache.set(
        ProjectOwnership.get_cache_key(instance.project_id), instance,
        READ_CACHE_DURATION),
    sender=ProjectOwnership,
    weak=False,
)
post_delete.connect(
    lambda instance, **kwargs: cache.set(
        ProjectOwnership.get_cache_key(instance.project_id), False,
        READ_CACHE_DURATION),
    sender=ProjectOwnership,
    weak=False,
)
示例#32
0
                    sc.save()
                    sc.marks_set.create(name='Internal test 1')
                    sc.marks_set.create(name='Internal test 2')
                    sc.marks_set.create(name='Internal test 3')
                    sc.marks_set.create(name='Event 1')
                    sc.marks_set.create(name='Event 2')
                    sc.marks_set.create(name='Semester End Exam')


def create_marks_class(sender, instance, **kwargs):
    if kwargs['created']:
        for name in test_name:
            try:
                MarksClass.objects.get(assign=instance, name=name[0])
            except MarksClass.DoesNotExist:
                m = MarksClass(assign=instance, name=name[0])
                m.save()


def delete_marks(sender, instance, **kwargs):
    stud_list = instance.class_id.student_set.all()
    StudentCourse.objects.filter(course=instance.course,
                                 student__in=stud_list).delete()


post_save.connect(create_marks, sender=Student)
post_save.connect(create_marks, sender=Assign)
post_save.connect(create_marks_class, sender=Assign)
post_save.connect(create_attendance, sender=AssignTime)
post_delete.connect(delete_marks, sender=Assign)
示例#33
0
        cache.add(keyfmt(FLAG_USERS_CACHE_KEY, f.name), f.users.all())
        cache.add(keyfmt(FLAG_GROUPS_CACHE_KEY, f.name), f.groups.all())


def uncache_flag(**kwargs):
    flag = kwargs.get('instance')
    data = {
        keyfmt(FLAG_CACHE_KEY, flag.name): None,
        keyfmt(FLAG_USERS_CACHE_KEY, flag.name): None,
        keyfmt(FLAG_GROUPS_CACHE_KEY, flag.name): None,
        keyfmt(FLAGS_ALL_CACHE_KEY): None
    }
    cache.set_many(data, 5)

post_save.connect(uncache_flag, sender=Flag, dispatch_uid='save_flag')
post_delete.connect(uncache_flag, sender=Flag, dispatch_uid='delete_flag')
m2m_changed.connect(uncache_flag, sender=Flag.users.through,
                    dispatch_uid='m2m_flag_users')
m2m_changed.connect(uncache_flag, sender=Flag.groups.through,
                    dispatch_uid='m2m_flag_groups')


def cache_sample(**kwargs):
    sample = kwargs.get('instance')
    cache.add(keyfmt(SAMPLE_CACHE_KEY, sample.name), sample)


def uncache_sample(**kwargs):
    sample = kwargs.get('instance')
    cache.set(keyfmt(SAMPLE_CACHE_KEY, sample.name), None, 5)
    cache.set(keyfmt(SAMPLES_ALL_CACHE_KEY), None, 5)
示例#34
0
class ArchAdmin(admin.ModelAdmin):
    list_display = ('name',)

class ImageTypeAdmin(admin.ModelAdmin):
    list_display = ('name',)

class TokenAdmin(admin.ModelAdmin):
    list_display = ('name',)

class JobStateAdmin(admin.ModelAdmin):
    list_display = ('name',)

class PostProcessAdmin(admin.ModelAdmin):
    list_display = ('name',)

admin.site.register(ImageJob, ImageJobAdmin)
admin.site.register(Queue, QueueAdmin)
admin.site.register(BuildService, BuildServiceAdmin)
admin.site.register(Arch, ArchAdmin)
admin.site.register(ImageType, ImageTypeAdmin)
admin.site.register(Token, TokenAdmin)
admin.site.register(JobState, JobStateAdmin)
admin.site.register(PostProcess, PostProcessAdmin)

post_save.connect(imagejob_save_callback, sender=ImageJob, weak=False,
                  dispatch_uid="imagejob_save_callback")

post_delete.connect(imagejob_delete_callback, sender=ImageJob, weak=False,
                    dispatch_uid="imagejob_delete_callback")
示例#35
0
# Create your models here.

class post(models.Model):

    Tittle=models.CharField(max_length=50)

    def __str__(self):
        return self.Tittle

def save_post(sender, instance, **kwargs):
    print("post save is call")

def save_pre(sender, instance, **kwargs):
    print("pre save is call")


#create delete function
def after_delete_post(sender, instance, **kwargs):
    print("you delete somthing")

post_save.connect(save_post, sender=post)

#this is a pre_save 
pre_save.connect(save_pre, sender=post) 

#the first 'somthing' is being called at the begning of the save method 
#the secound 'somthing' is being called at the end of the save method 

post_delete.connect(after_delete_post, sender=post)
示例#36
0
def connect_signals():
    for model in find_models_with_filefield():
        pre_save.connect(remove_old_files, sender=model)
        post_delete.connect(remove_files, sender=model)
    from_mail = '*****@*****.**'
    to_mail = [
        instance.user.email,
    ]
    context = {
        'name': instance.user.username,
        'expire_date': instance.expired_at,
    }
    message = get_template('mesages/message-template.html').render(context)

    msg = EmailMultiAlternatives(subject, message, from_mail, [to_mail])
    msg.attach_alternative(message, "text/html")
    msg.send()


post_delete.connect(send_notification, sender=Reservation)


class UserViewSet(viewsets.ModelViewSet):
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.IsAuthenticated, )
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['username', 'email']
    search_fields = ['^username', '^email']


#######################################################3


class HotelViewSet(viewsets.ModelViewSet):
示例#38
0
def create_user(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


# Method that catches the "save User event" and automatically saves the changes made to a profile
def save_profile(sender, instance, **kwargs):
    instance.profile.save()


# Creates the callback so that whenever a muestra is deleted; then the image associated is too
def delete_muestra_callback(sender, instance, **kwargs):

    url = instance.url_img
    ## does something with url to delete from firebase


def delete_user_callback(sender, instance, **kwargs):

    # We emulate the cascade effect
    for sesion in Sesion.objects.filter(id_usuario=instance.id):
        sesion.delete()


# Connect the callbacks to the signal they should be listening to
post_save.connect(create_user, sender=User)
post_save.connect(save_profile, sender=User)

post_delete.connect(delete_muestra_callback, sender=Muestra)
post_delete.connect(delete_user_callback, sender=User)
示例#39
0
    class Meta:
        app_label = "sentry"
        db_table = "sentry_externalactor"
        unique_together = (("organization", "provider", "external_name", "actor"),)

    def delete(self, **kwargs):
        from sentry.models import NotificationSetting

        # There is no foreign key relationship so we have to manually cascade.
        NotificationSetting.objects._filter(
            target_ids=[self.actor_id], provider=ExternalProviders(self.provider)
        ).delete()

        return super().delete(**kwargs)


post_save.connect(
    lambda instance, **kwargs: update_code_owners_schema.apply_async(
        kwargs={"organization": instance.organization, "integration": instance.integration}
    ),
    sender=ExternalActor,
    weak=False,
)
post_delete.connect(
    lambda instance, **kwargs: update_code_owners_schema.apply_async(
        kwargs={"organization": instance.organization, "integration": instance.integration}
    ),
    sender=ExternalActor,
    weak=False,
)
示例#40
0
Signals sent when saving REST API Keys.
Derived from django-apikey,
copyright (c) 2011 Steve Scoursen and Jorge Eduardo Cardona.
BSD license.
http://pypi.python.org/pypi/django-apikey
"""

from django.db.models.signals import post_save
from django.db.models.signals import post_delete
from .models import ApiKey


def save_api_key(sender, instance, created, **kwargs):
    try:
        instance.user.get_profile().save()
    except:
        pass


post_save.connect(save_api_key, sender=ApiKey)


def post_delete_api_key(sender, instance, **kwargs):
    try:
        instance.user.get_profile().save()
    except:
        pass


post_delete.connect(post_delete_api_key, sender=ApiKey)
示例#41
0
        self.key = key
        self.secret = secret
        self.save()

    # -- OAuth 1.0a stuff

    def get_callback_url(self):
        if self.callback and self.verifier:
            # Append the oauth_verifier.
            parts = urlparse.urlparse(self.callback)
            scheme, netloc, path, params, query, fragment = parts[:6]
            if query:
                query = '{0!s}&oauth_verifier={1!s}'.format(
                    query, self.verifier)
            else:
                query = 'oauth_verifier={0!s}'.format(self.verifier)
            return urlparse.urlunparse(
                (scheme, netloc, path, params, query, fragment))
        return self.callback

    def set_callback(self, callback):
        if callback != "oob":  # out of band, says "we can't do this!"
            self.callback = callback
            self.callback_confirmed = True
            self.save()


# Attach our signals
post_save.connect(consumer_post_save, sender=Consumer)
post_delete.connect(consumer_post_delete, sender=Consumer)
示例#42
0
            isinstance(self.data_value, basestring) and
            (self.data_value.startswith('xform') or
             self.data_value.startswith('dataview'))
        )

    @staticmethod
    def xform_meta_permission(content_object, data_value=None):
        data_type = XFORM_META_PERMS

        return unique_type_for_form(
            content_object, data_type, data_value)


def clear_cached_metadata_instance_object(
        sender, instance=None, created=False, **kwargs):
    safe_delete('{}{}'.format(
        XFORM_METADATA_CACHE, instance.object_id))


def update_attached_object(sender, instance=None, created=False, **kwargs):
    if instance:
        instance.content_object.save()


post_save.connect(clear_cached_metadata_instance_object, sender=MetaData,
                  dispatch_uid='clear_cached_metadata_instance_object')
post_save.connect(update_attached_object, sender=MetaData,
                  dispatch_uid='update_attached_xform')
post_delete.connect(clear_cached_metadata_instance_object, sender=MetaData,
                    dispatch_uid='clear_cached_metadata_instance_delete')
示例#43
0
    # if os.path.isfile(filename):
    #     os.remove(filename)
    # # delete folder only if empty
    # if path:
    #     if not os.listdir(path):
    #         os.rmdir(path)


def auto_delete_images_on_project_delete(sender, instance, **kwargs):
    if instance.title:
        images = Images.objects.filter(project__slug__iexact=instance.slug)
        if images:
            for imag in images:
                if imag:
                    imag.delete()


def post_delete_project(sender, instance, **kwargs):
    if instance.position:
        position = instance.position
        projects = Project.objects.order_by('position').filter(
            position__gt=position)
        for proj in projects:
            proj.update_position(-1)


pre_delete.connect(auto_delete_images_on_project_delete, sender=Project)
post_delete.connect(auto_delete_file_on_delete, sender=CV)
post_delete.connect(post_delete_project, sender=Project)
post_delete.connect(auto_delete_file_on_delete, sender=Images)
示例#44
0
    @classmethod
    def exports_outdated(cls, xform, export_type, options={}):
        # get newest export for xform
        try:
            export_options = get_export_options_query_kwargs(options)
            latest_export = Export.objects.filter(
                xform=xform,
                export_type=export_type,
                internal_status__in=[Export.SUCCESSFUL, Export.PENDING],
                **export_options).latest('created_on')
        except cls.DoesNotExist:
            return True
        else:
            if latest_export.time_of_last_submission is not None \
                    and xform.time_of_last_submission_update() is not None:
                return latest_export.time_of_last_submission <\
                    xform.time_of_last_submission_update()
            else:
                # return true if we can't determine the status, to force
                # auto-generation
                return True

    @classmethod
    def is_filename_unique(cls, xform, filename):
        return Export.objects.filter(xform=xform,
                                     filename=filename).count() == 0


post_delete.connect(export_delete_callback, sender=Export)
示例#45
0
def post_delete_sound(sender, instance, **kwargs):
    # after deleted sound update num_sound on profile and pack
    try:
        instance.user.profile.update_num_sounds()
    except ObjectDoesNotExist:
        # If this is triggered after user.delete() (instead of sound.delete() or user.profile.delete_user()),
        # user object will have no profile
        pass
    if instance.pack:
        instance.pack.process()
    web_logger.debug("Deleted sound with id %i" % instance.id)


pre_delete.connect(on_delete_sound, sender=Sound)
post_delete.connect(post_delete_sound, sender=Sound)


class PackManager(models.Manager):
    def ordered_ids(self, pack_ids, select_related=''):
        # Simplified version of ordered_ids in SoundManager (no need for custom SQL here)
        packs = {
            pack_obj.id: pack_obj
            for pack_obj in Pack.objects.select_related(select_related).filter(
                id__in=pack_ids).exclude(is_deleted=True)
        }
        return [packs[pack_id] for pack_id in pack_ids if pack_id in packs]


class Pack(SocialModel):
    user = models.ForeignKey(User)
示例#46
0
post_save.connect(post_save_ingredients_in_order,
                  sender=PizzaIngredientInOrder)


def post_delete_ingredients_in_order(sender, instance, *args, **kwargs):
    all_ingredients_in_order = PizzaIngredientInOrder.objects.filter(
        order=instance.order, is_active=True)
    order_total_price = 0
    for ingredient in all_ingredients_in_order:
        order_total_price += ingredient.total_price

    instance.order.total_price = order_total_price
    instance.order.save(force_update=True)


post_delete.connect(post_delete_ingredients_in_order,
                    sender=PizzaIngredientInOrder)


class IngredientsInBasket(models.Model):
    session_key = models.CharField(max_length=128, default=None)
    order = models.ForeignKey(Order,
                              blank=True,
                              null=True,
                              default=None,
                              on_delete=models.CASCADE)
    ingredient = models.ForeignKey(PizzaIngredient,
                                   blank=True,
                                   null=True,
                                   default=None,
                                   on_delete=models.CASCADE)
    nmb = models.IntegerField("Quantity", default=1)

def update_profile_num_submissions(sender, instance, **kwargs):
    profile_qs = User.profile.get_queryset()
    try:
        profile = profile_qs.select_for_update()\
            .get(pk=instance.user.profile.pk)
    except ObjectDoesNotExist:
        pass
    else:
        profile.num_of_submissions -= instance.num_of_submissions
        if profile.num_of_submissions < 0:
            profile.num_of_submissions = 0
        profile.save(update_fields=['num_of_submissions'])


post_delete.connect(update_profile_num_submissions,
                    sender=XForm,
                    dispatch_uid='update_profile_num_submissions')


def set_object_permissions(sender, instance=None, created=False, **kwargs):
    if created:
        for perm in get_perms_for_model(XForm):
            assign_perm(perm.codename, instance.user, instance)


post_save.connect(set_object_permissions,
                  sender=XForm,
                  dispatch_uid='xform_object_permissions')
示例#48
0
            else:
                raise Exception(u"Handler already registered for type %s" % type)
            return handler

        return inner

    @classmethod
    def get_registered_type(cls, type):
        return cls._type_registrations[type]

    @classmethod
    def get_registered_types(cls):
        return cls._type_registrations.values()


post_delete.connect(AlertRuleManager.clear_subscription_cache, sender=QuerySubscription)
post_save.connect(AlertRuleManager.clear_subscription_cache, sender=QuerySubscription)
post_save.connect(AlertRuleManager.clear_alert_rule_subscription_caches, sender=AlertRule)
post_delete.connect(AlertRuleManager.clear_alert_rule_subscription_caches, sender=AlertRule)

post_delete.connect(AlertRuleTriggerManager.clear_alert_rule_trigger_cache, sender=AlertRule)
post_save.connect(AlertRuleTriggerManager.clear_alert_rule_trigger_cache, sender=AlertRule)
post_save.connect(AlertRuleTriggerManager.clear_trigger_cache, sender=AlertRuleTrigger)
post_delete.connect(AlertRuleTriggerManager.clear_trigger_cache, sender=AlertRuleTrigger)

post_save.connect(IncidentManager.clear_active_incident_cache, sender=Incident)
post_save.connect(IncidentManager.clear_active_incident_project_cache, sender=IncidentProject)
post_delete.connect(IncidentManager.clear_active_incident_project_cache, sender=IncidentProject)

post_delete.connect(IncidentTriggerManager.clear_incident_cache, sender=Incident)
post_save.connect(IncidentTriggerManager.clear_incident_trigger_cache, sender=IncidentTrigger)
示例#49
0
    @property
    def exists(self):
        try:
            return bool(self.file_object.size)
        except OSError:
            return False

    def get_mime(self):
        return guess_type(self.file_object.path)[0]

    def is_passed(self):
        return self.get_mime() in SubmittedFile.PASS_MIME

    ABSOLUTE_URL_NAME = "submission-file"

    def get_url_kwargs(self):
        return dict(file_id=self.id,
                    file_name=self.filename,
                    **self.submission.get_url_kwargs())


def _delete_file(sender, instance, **kwargs):
    """
    Deletes the actual submission files after the submission in database is
    removed.
    """
    instance.file_object.delete(save=False)


post_delete.connect(_delete_file, SubmittedFile)
示例#50
0
    cache.set('api_updated_topic', datetime.datetime.utcnow())


def change_api_private_post_updated_at(sender=None, instance=None, *args, **kwargs):
    cache.set('api_updated_post', datetime.datetime.utcnow())


def change_api_notification_updated_at(sender=None, instance=None, *args, **kwargs):
    cache.set('api_updated_notification', datetime.datetime.utcnow())


for model, func in [(PrivateTopic, change_api_private_topic_updated_at),
                    (PrivatePost, change_api_private_post_updated_at),
                    (Notification, change_api_notification_updated_at)]:
    post_save.connect(receiver=func, sender=model)
    post_delete.connect(receiver=func, sender=model)


class PrivateTopicListAPI(LeavePrivateTopic, ListCreateAPIView, DestroyAPIView):
    """
    Private topic resource to list of a member.
    """

    filter_backends = (filters.SearchFilter, filters.OrderingFilter)
    search_fields = ('title',)
    ordering_fields = ('pubdate', 'last_message', 'title')
    list_key_func = PagingPrivateTopicListKeyConstructor()

    @etag(list_key_func)
    @cache_response(key_func=list_key_func)
    def get(self, request, *args, **kwargs):
示例#51
0
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# (ɔ) Copyleft 2007-2008 Stefan Imhoff
# Licensed under the GNU General Public License, version 3.
# http://www.gnu.org/copyleft/gpl.txt

from django.db.models.signals import post_save, post_delete
from encyclopedia.models import Entry
from encyclopedia.signals import purge_cache

post_save.connect(purge_cache, sender=Entry)
post_delete.connect(purge_cache, sender=Entry)
示例#52
0
    created_at = models.DateTimeField(auto_now=True)
    app_label = models.CharField(max_length=255)
    model_name = models.CharField(max_length=255)
    action = models.CharField(max_length=50)

    @classmethod
    def log(cls, instance, action):
        # exclude ModelLog changes from log
        if not isinstance(instance, ModelLog):
            try:
                entry = ModelLog(app_label=instance._meta.app_label,
                                 model_name=instance.__class__.__name__,
                                 action=action)
                entry.save()
            except DatabaseError:
                pass


def log_update_create(sender, instance, created, **kwargs):
    ModelLog.log(instance,
                 ModelLog.ACTION_CREATE if created else ModelLog.ACTION_UPDATE)


def log_delete(sender, instance, **kwargs):
    ModelLog.log(instance, ModelLog.ACTION_DELETE)


post_save.connect(log_update_create, dispatch_uid='log_update_create')
post_delete.connect(log_delete, dispatch_uid='log_delete')
示例#53
0

def sync_model_product_delete(sender, instance, *args, **kwargs):
    """
    当删除排期中的明细的时候 需要将 对应ModelProduct的上下架时间置为 None
    防止录入资料后有排期明细的改动 导致 按照日期的错误上架
    """
    # 对应上架时间的款式
    modelproducts = instance.modelproducts.filter(
        onshelf_time=instance.schedule_manage.upshelf_time)
    for modelproduct in modelproducts:
        modelproduct.set_shelftime_none()


post_delete.connect(sync_model_product_delete,
                    SaleProductManageDetail,
                    dispatch_uid=u'post_delete_sync_model_product_delete')


class SaleProductSku(models.Model):
    outer_id = models.CharField(max_length=64,
                                blank=True,
                                verbose_name=u'外部ID')

    product_color = models.CharField(max_length=64,
                                     blank=True,
                                     verbose_name=u'颜色')
    pic_url = models.CharField(max_length=512,
                               blank=True,
                               verbose_name=u'商品图片')
    properties_name = models.CharField(max_length=64,
示例#54
0
    def _get_config(self):
        try:
            return self.config_model._default_manager.all()[0]
        except IndexError:
            pass

    config = property(_get_config)

    def render(self, request=None):
        renderer = import_by_path(self.homepage_section_renderer)
        return renderer(self, request)


def delete_object_events(sender, **kwargs):
    """
    Receiver of the post_delete signal that also deletes any ConsoleEvent
    targeting the recently deleted object. This to ensure that we do not
    attempt to render an event which matching object was deleted and thus
    causing an error on the Console.
    """
    if sender == ConsoleEvent:  # Avoid unending recursive call
        return
    instance = kwargs['instance']
    from ikwen.accesscontrol.backends import UMBRELLA

    ConsoleEvent.objects.using(UMBRELLA).filter(object_id=instance.pk).delete()


post_delete.connect(delete_object_events, dispatch_uid="object_post_delete_id")
示例#55
0
                    'LogEntry content_type and object_id must both be set or both be None.'
                )
            # Ensure that the object_id (primary key) is valid:
            if not self.content_type.get_all_objects_for_this_type(
                    pk=self.object_id).exists():
                raise ValidationError({
                    'object_id':
                    'Object attached to LogEntry has bad content_type or primary key'
                })

    @staticmethod
    def on_post_delete(sender, instance, **kwargs):
        """
        Whenever an object is deleted, check if there are corresponding log entries to delete.
        """
        if isinstance(instance,
                      LogEntry) or instance._meta.app_label == 'migrations':
            return  # Avoid pointless database queries when deleting log entries themselves or saving migration history
        if not isinstance(instance.pk, int):
            return  # Current LogEntry schema requires integer objects IDs, so we know this object isn't in the table
        content_type = ContentType.objects.get_for_model(instance)
        num_deleted, dummy = LogEntry.objects.filter(
            content_type=content_type, object_id=instance.pk).delete()
        if num_deleted > 0:
            logger.info(
                'Deleted %d log entries for deleted %s instance with ID %d',
                num_deleted, content_type.name, instance.pk)


post_delete.connect(LogEntry.on_post_delete)
示例#56
0

# comments have no revision history, and allow minimum makeup.
class AbstractComment(models.Model):
    content = models.TextField(max_length=600, null=False)
    last_modified = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        self.last_modified = timezone.now()
        return super(AbstractPost, self).save(*args, **kwargs)

    class Meta:
        abstract = True


class MainPostComment(AbstractComment):
    post = models.ForeignKey(MainPost,
                             related_name="comments",
                             verbose_name=_("main post comment"))


class ReplyPostComment(AbstractComment):
    post = models.ForeignKey(ReplyPost,
                             related_name="comments",
                             verbose_name=_("reply post comment"))


post_save.connect(MainPost.reset_reply_count, sender=ReplyPost)
post_delete.connect(MainPost.reset_reply_count, sender=ReplyPost)
示例#57
0
                key2 = make_template_fragment_key(
                    'sprintboard_issue_template',
                    [iss.project.name_short, iss.number, user.username])
                cache.delete(key2)


post_save.connect(invalidate_cache,
                  sender=Issue,
                  dispatch_uid="invalidate_issue_template.cards_post_save")
m2m_changed.connect(invalidate_cache,
                    sender=Issue.tags.through,
                    dispatch_uid="invalidate_issue_template.cards_tags")
m2m_changed.connect(invalidate_cache,
                    sender=Issue.assignee.through,
                    dispatch_uid="invalidate_issue_template.cards_assignee")
m2m_changed.connect(invalidate_cache,
                    sender=Issue.participant.through,
                    dispatch_uid="invalidate_issue_template.cards_participant")
post_save.connect(
    invalidate_cache,
    sender=Punch,
    dispatch_uid="invalidate_issue_template.cards_punch_post_init")
post_delete.connect(
    invalidate_cache,
    sender=Punch,
    dispatch_uid="invalidate_issue_template.cards_punch_post_delete")
post_save.connect(
    invalidate_cache,
    sender=Sprint,
    dispatch_uid="invalidate_issue_template.cards_punch_post_sprint")
示例#58
0
def chdir(path):
    try:
        os.chdir(path)
        return True
    except Exception, e:
        logger.exception(e)
    return False


def stop():
    EventManager.send_stop_event(FORK_TUBE_NAME)
    logger.info('send stop event message...')


def __cache_version_update(sender, **kwargs):
    da_post_save(kwargs['instance'])


if __name__ == '__main__':
    post_save.connect(__cache_version_update)
    post_delete.connect(__cache_version_update)
    if len(sys.argv) < 2:
        print 'usage: start|stop'
        sys.exit(1)
    action = sys.argv[1]
    if action == 'start':
        start()
    elif action == 'stop':
        stop()
示例#59
0
def cartitem_pre_action_receiver(sender, instance, *args, **kwargs):
    qty = instance.quantity
    if qty >= 1:
        price = Decimal(instance.variation.get_price())
        instance.items_total = price * qty

pre_save.connect(cartitem_pre_action_receiver, sender=CartItem)


def cartitem_post_action_receiver(sender, instance, *args, **kwargs):
    instance.cart.update_subtotal()


post_save.connect(cartitem_post_action_receiver, sender=CartItem)
post_delete.connect(cartitem_post_action_receiver, sender=CartItem)


class Cart(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True)
    items = models.ManyToManyField(Variation, through=CartItem)
    # timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    # updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    subtotal = models.DecimalField(max_digits=20, decimal_places=2, default=0.00)
    tax_total = models.DecimalField(max_digits=20, decimal_places=2, default=0.00)
    total = models.DecimalField(max_digits=20, decimal_places=2, default=0.00)
    tax_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0.23)

    def __str__(self):
        return str(self.id)
示例#60
0
        def __init__(self, model_cls, rel_field_name):
            self._rel_field_name = rel_field_name

            if django.VERSION >= (1, 7):
                # Django >= 1.7
                self._rel_field = model_cls._meta.get_field(rel_field_name)
                rel_model = self._rel_field.model
                is_rel_direct = (not self._rel_field.auto_created
                                 or self._rel_field.concrete)
                is_m2m = self._rel_field.many_to_many
            else:
                # Django < 1.7
                self._rel_field, rel_model, is_rel_direct, is_m2m = \
                    model_cls._meta.get_field_by_name(rel_field_name)

            self._is_rel_reverse = not is_rel_direct

            if not is_m2m and is_rel_direct:
                # This combination doesn't make any sense. There's only ever
                # one item on this side, so no point in counting. Let's just
                # complain about it.
                raise ValueError(
                    "RelationCounterField cannot work with the forward end of "
                    "a ForeignKey ('%s')" % rel_field_name)

            dispatch_uid = '%s-%s.%s-related-save' % (
                id(self), self.__class__.__module__, self.__class__.__name__)

            if is_m2m:
                # This is going to be one end or the other of a ManyToManyField
                # relation.
                if is_rel_direct:
                    # This is a ManyToManyField, and we can get the 'rel'
                    # attribute through it.
                    m2m_field = self._rel_field
                    self._related_name = m2m_field.rel.related_name
                else:
                    # This is a RelatedObject. We need to get the field through
                    # this.
                    m2m_field = self._rel_field.field
                    self._related_name = m2m_field.attname

                # Listen for all M2M updates on the through table for this
                # ManyToManyField. Unfortunately, we can't look at a
                # particular instance, but we'll use state tracking to do the
                # necessary lookups and updates in the handler.
                m2m_changed.connect(self._on_m2m_changed,
                                    weak=False,
                                    sender=m2m_field.rel.through,
                                    dispatch_uid=dispatch_uid)
            else:
                # This is a ForeignKey or similar. It must be the reverse end.
                assert not is_rel_direct

                model = self._get_rel_field_related_model(self._rel_field)
                self._related_name = self._rel_field.field.attname

                # Listen for deletions and saves on that model type. In the
                # handler, we'll look up state for the other end of the
                # relation (the side owning this RelationCounterField), so that
                # we can update the counts.
                #
                # Unfortunately, we can't listen on the particular instance, so
                # we use the state tracking.
                post_delete.connect(self._on_related_delete,
                                    weak=False,
                                    sender=model,
                                    dispatch_uid=dispatch_uid)
                post_save.connect(self._on_related_save,
                                  weak=False,
                                  sender=model,
                                  dispatch_uid=dispatch_uid)