def install_cacheops(): """ Installs cacheops by numerous monkey patches """ global installed if installed: return # just return for now, second call is probably done due cycle imports installed = True monkey_mix(Manager, ManagerMixin) monkey_mix(QuerySet, QuerySetMixin) monkey_mix(ValuesQuerySet, QuerySetMixin, ['iterator']) monkey_mix(ValuesListQuerySet, QuerySetMixin, ['iterator']) monkey_mix(DateQuerySet, QuerySetMixin, ['iterator']) # Install profile and signal handlers for any earlier created models from django.db.models import get_models for model in get_models(include_auto_created=True): model._default_manager._install_cacheops(model) # Turn off caching in admin from django.conf import settings if 'django.contrib.admin' in settings.INSTALLED_APPS: from django.contrib.admin.options import ModelAdmin def ModelAdmin_queryset(self, request): return o_ModelAdmin_queryset(self, request).nocache() o_ModelAdmin_queryset = ModelAdmin.queryset ModelAdmin.queryset = ModelAdmin_queryset # bind m2m changed handler m2m_changed.connect(invalidate_m2m)
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)
def ready(self): from .models import AdditionalInformationForPrice from .signals import m2m_changed_information m2m_changed.connect( receiver=m2m_changed_information, sender=AdditionalInformationForPrice.information.through )
def install_cacheops(): """ Installs cacheops by numerous monkey patches """ monkey_mix(Manager, ManagerMixin) monkey_mix(QuerySet, QuerySetMixin) monkey_mix(ValuesQuerySet, QuerySetMixin, ['iterator']) monkey_mix(ValuesListQuerySet, QuerySetMixin, ['iterator']) monkey_mix(DateQuerySet, QuerySetMixin, ['iterator']) # Install profile and signal handlers for any earlier created models from django.db.models import get_models for model in get_models(include_auto_created=True): model._default_manager._install_cacheops(model) # Turn off caching in admin from django.contrib.admin.options import ModelAdmin def ModelAdmin_queryset(self, request): queryset = o_ModelAdmin_queryset(self, request) if queryset._cacheprofile is None: return queryset else: return queryset.nocache() o_ModelAdmin_queryset = ModelAdmin.queryset ModelAdmin.queryset = ModelAdmin_queryset # bind m2m changed handler m2m_changed.connect(invalidate_m2m)
def register_poster(self, model, stream_field, *actions): field = getattr(model, stream_field).field stream = field.rel.to if isinstance(stream, str): stream = get_model(*stream.split('.')) if not stream in self._registry: raise NotRegistered('Model %s not registered.' % stream) self._models[model] = stream_field if isinstance(field, ForeignKey): self.logger.debug( 'Registered poster model %s for stream model %s' % ( model._meta.verbose_name.capitalize(), stream._meta.verbose_name.capitalize() ) ) elif isinstance(field, ManyToManyField): m2m_changed.connect(receivers.m2m_changed) self.logger.debug( 'Registered poster model %s for many-to-many stream model %s' % ( model._meta.verbose_name.capitalize(), stream._meta.verbose_name.capitalize() ) ) else: raise ImproperlyConfigured('Connecting field must be a ForeignKey or ManyToMany field') pre_save.connect(receivers.pre_save, sender = model) pre_delete.connect(receivers.pre_delete, sender = model) post_save.connect(receivers.post_save, sender = model)
def register(self, model_or_iterable, model_metatags_class=None, **options): if not model_metatags_class: model_metatags_class = ModelMetatags 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( u'The model %s already registered' % model.__name__) self._append_inline_instance(model) if options: options['__module__'] = __name__ model_metatags_class = type( '%sMetatags' % model.__name__, (model_metatags_class,), options) model_metatags = model_metatags_class() self._registry[model] = model_metatags pre_delete.connect(self.delete_metatag, sender=model) post_save.connect(self.check_metatag_url_path, sender=model) post_save.connect(self.check_metatag_language, sender=model) sites_field_class = model_metatags.sites_field_class(model) if sites_field_class is ManyToManyField: through_model = getattr( model, model_metatags.sites_field_name).through m2m_changed.connect( self.check_metatag_sites, sender=through_model) else: post_save.connect(self.check_metatag_site, sender=model)
def test_admin_form_should_stop_user_demoting_themselves(self): self.login() from models import IntranetGroup manager = IntranetGroup.objects.get(name="Manager") self.assertTrue(manager.administrators, """This test will not work unless the Manager group's administrators flag is set""") self.assertTrue(self.current_user.is_superuser) self.assertIn(manager.group, self.current_user.groups.all()) url = reverse('admin:binder_intranetuser_change', args=[self.current_user.id]) response = self.client.get(url) # POST without changing anything should be fine form = self.assertInDict('adminform', response.context).form new_values = self.update_form_values(form) response = self.client.post(url, new_values, follow=True) self.assert_changelist_not_admin_form_with_errors(response) # but changing the group should result in an error user = IntranetGroup.objects.get(name="User") new_values = self.update_form_values(form, groups=[user.pk]) response = self.client.post(url, new_values) self.assert_admin_form_with_errors_not_changelist(response, {'groups': ['You cannot demote yourself from the %s group' % manager.name]}) # shouldn't be allowed to do anything that removes our superuser flag # remove us from manager group, but keep superuser flag. # temporarily disable the signal listener so that it doesn't # automatically demote us from superuser from django.db.models.signals import m2m_changed from django.dispatch import receiver m2m_changed.disconnect(sender=User.groups.through, receiver=IntranetUser.groups_changed, dispatch_uid="User_groups_changed") self.current_user.groups = [user] m2m_changed.connect(sender=User.groups.through, receiver=IntranetUser.groups_changed, dispatch_uid="User_groups_changed") self.current_user = self.current_user.reload() self.assertItemsEqual([user.group], self.current_user.groups.all()) self.assertTrue(self.current_user.is_superuser) # now we're not removing ourselves from any groups, but saving # would still demote us automatically from being a superuser. response = self.client.post(url, new_values) self.assert_admin_form_with_errors_not_changelist(response, {'groups': ['You cannot demote yourself from being a superuser. ' + 'You must put yourself in one of the Administrators groups: ' + '%s' % IntranetGroup.objects.filter(administrators=True)]}) # we shouldn't be allowed to delete ourselves either deleted = IntranetGroup.objects.get(name="Deleted") user = IntranetGroup.objects.get(name="User") new_values = self.update_form_values(form, groups=[manager.pk, deleted.pk]) # import pdb; pdb.set_trace() response = self.client.post(url, new_values) self.assert_admin_form_with_errors_not_changelist(response, {'groups': ['You cannot place yourself in the %s group' % deleted.name]})
def ready(self): RabbitWorker().declare_exchange() from models import Collection, Export from sched import start_sched, schedule_harvest_receiver, unschedule_harvest_receiver from export import export_receiver, export_m2m_receiver from notifications import send_user_harvest_emails if settings.SCHEDULE_HARVESTS: log.debug("Setting receivers for collections.") post_save.connect(schedule_harvest_receiver, sender=Collection) pre_delete.connect(unschedule_harvest_receiver, sender=Collection) # Export if settings.PERFORM_EXPORTS: log.debug("Setting receiver for exports.") post_save.connect(export_receiver, sender=Export) m2m_changed.connect(export_m2m_receiver, sender=Export.seeds.through) # Add 5 minute interval if settings.FIVE_MINUTE_SCHEDULE: log.debug("Adding 5 minute timer") Collection.SCHEDULE_CHOICES.append((5, "Every 5 minutes")) if settings.RUN_SCHEDULER: log.debug("Running scheduler") sched = start_sched() if settings.PERFORM_USER_HARVEST_EMAILS: if sched.get_job('user_harvest_emails') is not None: sched.remove_job('user_harvest_emails') sched.add_job(send_user_harvest_emails, 'cron', hour=settings.USER_HARVEST_EMAILS_HOUR, minute=settings.USER_HARVEST_EMAILS_MINUTE, id='user_harvest_emails') else: log.debug("Not running scheduler")
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 _connect_signal_handlers(self): post_save.connect(self.handle_object_update, sender=self.model) pre_delete.connect(self.handle_object_deletion, sender=self.model) sites_field_class = self.sites_field_class() if sites_field_class is ManyToManyField: self._through = getattr(self.model, self.sites_field_name).through m2m_changed.connect(self.handle_object_update, self._through)
def register_signals(): from c3nav.mapdata.models.geometry.base import GeometryMixin for model in get_submodels(GeometryMixin): post_delete.connect(geometry_deleted, sender=model) from c3nav.mapdata.models.locations import SpecificLocation for model in get_submodels(SpecificLocation): m2m_changed.connect(locationgroup_changed, sender=model.groups.through)
def finalize(): for relation in modules.tax.Tax.m2m_invalidations: field = getattr(modules.tax.Tax, relation) m2m_changed.connect(on_tax_m2m_changed, sender=field.through) for subtype in modules.tax.subtypes: pre_save.connect(on_tax_pre_save, sender=subtype) post_save.connect(on_tax_post_save, sender=subtype) pre_delete.connect(on_tax_pre_delete, sender=subtype)
def test_m2m_changed_signal_is_fired(self): # Use object attrs instead of mocks for Django 1.4 compat self.m2m_changed_fired = False def test_m2m_changed(*args, **kwargs): self.m2m_changed_fired = True m2m_changed.connect(test_m2m_changed, dispatch_uid='test_m2m_changed') store = mommy.make(Store, make_m2m=True) self.assertTrue(self.m2m_changed_fired)
def register_signal_handlers(self, sender): post_save.connect(self.post_save, sender=sender, weak=False) post_delete.connect(self.post_delete, sender=sender, weak=False) get_m2m_through_classes = M2MThroughClassesGatherer(sender) through_classes = get_m2m_through_classes() for through_class in through_classes: m2m_changed.connect(self.m2m_changed, sender=through_class, weak=False)
def setup(self): super(AristotleChannelsSignalProcessor, self).setup() from aristotle_mdr.models import ReviewRequest, concept_visibility_updated post_save.connect(self.update_visibility_review_request, sender=ReviewRequest) m2m_changed.connect(self.update_visibility_review_request, sender=ReviewRequest.concepts.through) concept_visibility_updated.connect(self.handle_concept_recache)
def connect_signals(self): """ * m2m validation before templates are added to a config """ from .models import Config m2m_changed.connect(Config.clean_templates, sender=Config.templates.through) m2m_changed.connect(Config.templates_changed, sender=Config.templates.through)
def setup(self): from aristotle_mdr.models import _concept, Workgroup, ReviewRequest, concept_visibility_updated post_save.connect(self.handle_concept_save) # post_revision_commit.connect(self.handle_concept_revision) pre_delete.connect(self.handle_concept_delete, sender=_concept) post_save.connect(self.update_visibility_review_request, sender=ReviewRequest) m2m_changed.connect(self.update_visibility_review_request, sender=ReviewRequest.concepts.through) concept_visibility_updated.connect(self.handle_concept_recache) super(AristotleSignalProcessor, self).setup()
def ready(self): m2m_changed.connect( issue_tags_changed, sender=self.get_model('Issue').tags.through, dispatch_uid="tags_change" ) post_save.connect( issue_created, sender=self.get_model('Issue') )
def ready(self): from .models import MeetingInteraction, PhoneInteraction from .signals.handlers import set_attendees_string m2m_changed.connect( set_attendees_string, sender=PhoneInteraction.attendees.through) m2m_changed.connect( set_attendees_string, sender=MeetingInteraction.attendees.through) AppConfig.ready(self)
def install_cacheops(): """ Installs cacheops by numerous monkey patches """ monkey_mix(Manager, ManagerMixin) monkey_mix(QuerySet, QuerySetMixin) QuerySet._cacheprofile = QuerySetMixin._cacheprofile QuerySet._cloning = QuerySetMixin._cloning # DateQuerySet existed in Django 1.7 and earlier # Values*QuerySet existed in Django 1.8 and earlier from django.db.models import query for cls_name in ('ValuesQuerySet', 'ValuesListQuerySet', 'DateQuerySet'): if hasattr(query, cls_name): cls = getattr(query, cls_name) monkey_mix(cls, QuerySetMixin, ['iterator']) try: # Use app registry in Django 1.7 from django.apps import apps admin_used = apps.is_installed('django.contrib.admin') get_models = apps.get_models except ImportError: # Introspect INSTALLED_APPS in older djangos from django.conf import settings admin_used = 'django.contrib.admin' in settings.INSTALLED_APPS from django.db.models import get_models # Install profile and signal handlers for any earlier created models for model in get_models(include_auto_created=True): model._default_manager._install_cacheops(model) # Turn off caching in admin if admin_used: from django.contrib.admin.options import ModelAdmin # Renamed queryset to get_queryset in Django 1.6 method_name = 'get_queryset' if hasattr(ModelAdmin, 'get_queryset') else 'queryset' @monkey(ModelAdmin, name=method_name) def get_queryset(self, request): return get_queryset.original(self, request).nocache() # Bind m2m changed handler m2m_changed.connect(invalidate_m2m) # Make buffers/memoryviews pickleable to serialize binary field data if six.PY2: import copy_reg copy_reg.pickle(buffer, lambda b: (buffer, (bytes(b),))) if six.PY3: import copyreg copyreg.pickle(memoryview, lambda b: (memoryview, (bytes(b),)))
def setup(self): from aristotle_mdr.models import _concept, concept_visibility_updated from aristotle_mdr.contrib.reviews.models import ReviewRequest from aristotle_mdr.contrib.help.models import HelpPage, ConceptHelp post_save.connect(self.handle_concept_save) # post_revision_commit.connect(self.handle_concept_revision) pre_delete.connect(self.handle_concept_delete, sender=_concept) post_save.connect(self.update_visibility_review_request, sender=ReviewRequest) m2m_changed.connect(self.update_visibility_review_request, sender=ReviewRequest.concepts.through) concept_visibility_updated.connect(self.handle_concept_recache) post_save.connect(self.async_handle_save, sender=HelpPage) post_save.connect(self.async_handle_save, sender=ConceptHelp) super().setup()
def install_cacheops(): """ Installs cacheops by numerous monkey patches """ monkey_mix(Manager, ManagerMixin) monkey_mix(QuerySet, QuerySetMixin) # Use app registry to introspect used apps from django.apps import apps # Install profile and signal handlers for any earlier created models for model in apps.get_models(include_auto_created=True): if family_has_profile(model): if not isinstance(model._default_manager, Manager): raise ImproperlyConfigured("Can't install cacheops for %s.%s model:" " non-django model class or manager is used." % (model._meta.app_label, model._meta.model_name)) model._default_manager._install_cacheops(model) # Bind m2m changed handlers rel_attr = 'remote_field' if django.VERSION >= (1, 9) else 'rel' m2ms = (f for f in model._meta.get_fields(include_hidden=True) if f.many_to_many) for m2m in m2ms: rel = m2m if hasattr(m2m, 'through') else getattr(m2m, rel_attr, m2m) opts = rel.through._meta m2m_changed.connect(invalidate_m2m, sender=rel.through, dispatch_uid=(opts.app_label, opts.model_name)) # Turn off caching in admin if apps.is_installed('django.contrib.admin'): from django.contrib.admin.options import ModelAdmin @monkey(ModelAdmin) def get_queryset(self, request): return get_queryset.original(self, request).nocache() # Make buffers/memoryviews pickleable to serialize binary field data if six.PY2: import copy_reg copy_reg.pickle(buffer, lambda b: (buffer, (bytes(b),))) # noqa if six.PY3: import copyreg copyreg.pickle(memoryview, lambda b: (memoryview, (bytes(b),))) # Fix random ordered dict keys producing different SQL for same QuerySet if (3, 3) <= sys.version_info < (3, 6): from django.db.models.query_utils import Q def Q__init__(self, *args, **kwargs): # noqa super(Q, self).__init__(children=list(args) + list(sorted(kwargs.items()))) Q.__init__ = Q__init__
def ready(self): # connect m2m_changed signal for TrainingRequest.domains to calculate # score_auto TrainingRequest = self.get_model('TrainingRequest') m2m_changed.connect( trainingrequest_m2m_changed, sender=TrainingRequest.domains.through, ) m2m_changed.connect( trainingrequest_m2m_changed, sender=TrainingRequest.previous_involvement.through, )
def _track_class_field(cls, field): """ Track a field on the current model """ if '__' in field: _track_class_related_field(cls, field) return # Will raise FieldDoesNotExist if there is an error cls._meta.get_field(field) # Detect m2m fields changes if isinstance(cls._meta.get_field(field), ManyToManyField): m2m_changed.connect( tracking_m2m, sender=getattr(cls, field).through, dispatch_uid=repr(cls), )
def setup_discounts(): for relation in modules.discount.Discount.m2m_invalidations: field = getattr(modules.discount.Discount, relation) m2m_changed.connect(on_discount_m2m_changed, sender=field.through) for subtype in modules.discount.subtypes: pre_save.connect(on_discount_pre_save, sender=subtype) post_save.connect(on_discount_post_save, sender=subtype) pre_delete.connect(on_discount_pre_delete, sender=subtype) if modules.discount.user_discount_enabled: m2m_changed.connect( on_discount_groups_changed, sender=modules.discount.Discount.groups.through) post_save.connect( on_group_post_save, sender=modules.discount.DiscountGroup)
def turn_on_syncing(for_post_save=True, for_post_delete=True, for_m2m_changed=True, for_post_bulk_operation=False): """ Enables all of the signals for syncing entities. Everything is True by default, except for the post_bulk_operation signal. The reason for this is because when any bulk operation occurs on any mirrored entity model, it will result in every single entity being synced again. This is not a desired behavior by the majority of users, and should only be turned on explicitly. """ if for_post_save: post_save.connect(save_entity_signal_handler, dispatch_uid='save_entity_signal_handler') if for_post_delete: post_delete.connect(delete_entity_signal_handler, dispatch_uid='delete_entity_signal_handler') if for_m2m_changed: m2m_changed.connect(m2m_changed_entity_signal_handler, dispatch_uid='m2m_changed_entity_signal_handler') if for_post_bulk_operation: post_bulk_operation.connect(bulk_operation_signal_handler, dispatch_uid='bulk_operation_signal_handler')
def connect_signals(): post_save.connect(prepare_estate_childs, sender=Estate) post_save.connect(set_validity, sender=Estate) post_save.connect(set_validity, sender=Bidg) post_save.connect(set_validity, sender=Stead) post_save.connect(update_deleted, sender=Client) post_save.connect(update_estate, sender=Contact) post_save.connect(estate_client_handler, sender=EstateClient) post_delete.connect(estate_client_handler, sender=EstateClient) post_save.connect(update_geo, sender=Bid) # @UndefinedVariable pre_save.connect(update_from_pickle, sender=Bid) post_save.connect(bid_event_history, sender=BidEvent) post_save.connect(estate_wp_meta, sender=Estate) m2m_changed.connect(estate_param_wp_meta, sender=Estate.estate_params.through) # @UndefinedVariable post_save.connect(update_estate_m2m, sender=EntranceEstate) # @UndefinedVariable post_save.connect(update_estate_m2m, sender=EstatePhoto) # @UndefinedVariable post_save.connect(save_estate, sender=Layout)
def connect(self, model): """ Connect to the model. It is called in `Registry.register` method thus users should not call this method directly """ self.model = model self.app_label = model._meta.app_label # connect post_save/pre_delete signal post_save.connect(self._post_save_receiver, sender=model, weak=False) pre_delete.connect(self._pre_delete_receiver, sender=model, weak=False) # connect m2m_changed signal of all ManyToMany fields for m2m in self.get_m2m_fields(): m2m_changed.connect(self._m2m_changed_receiver, sender=m2m.rel.through, weak=False)
def connect(self): for signal_name in ('pre_migrate', 'post_migrate'): signal = globals()[signal_name] dispatch_uid = self.get_dispatch_uid(signal_name) signal.connect( getattr(self, 'on_{}'.format(signal_name)), sender=self.m2m_model_class._meta.app_config, dispatch_uid=dispatch_uid, ) log_trace('%r: connect %s', self, dispatch_uid) dispatch_uid = self.get_dispatch_uid('m2m_changed') m2m_changed.connect( self.on_m2m_changed, sender=self.m2m_model_class, dispatch_uid=dispatch_uid, ) log_trace('%r: connect %s', self, dispatch_uid)
def connect_signals(): from django.db.models.signals import pre_save, post_save, post_delete, pre_delete, m2m_changed from ella.core.signals import content_published, content_unpublished from ella.core.models import Listing, Publishable if not core_settings.USE_REDIS_FOR_LISTINGS: return # when redis is availible, use it for authors m2m_changed.connect(update_authors, sender=Publishable._meta.get_field('authors').rel.through) content_published.connect(publishable_published) content_unpublished.connect(publishable_unpublished) pre_save.connect(listing_pre_save, sender=Listing) post_save.connect(listing_post_save, sender=Listing) pre_delete.connect(listing_pre_delete, sender=Listing) post_delete.connect(listing_post_delete, sender=Listing)
def __str__(self): return str(self.id) def m2m_changed_carrinho_receiver( sender, instance, action, *args, **kwargs): # quando a venda é salva, chamamos este método if action == 'post_add' or action == 'post_remove' or action == 'post_clear': produtos = instance.produtos.all() total = 0 for item in produtos: total += item.price if instance.subtotal != total: instance.subtotal = total instance.save() m2m_changed.connect(m2m_changed_carrinho_receiver, sender=Carrinho.produtos.through) def pre_save_carrinho_receiver(sender, instance, *args, **kwargs): if instance.subtotal > 0: instance.total = instance.subtotal + 10 else: instance.total = 0.00 pre_save.connect(pre_save_carrinho_receiver, sender=Carrinho)
def increment_range_cache_version(sender, instance, **kwargs): instance.increment_cache_version() def invalidate_pricing_cache_ns(sender, instance, **kwargs): transaction.on_commit(lambda: pricing_cache_ns.invalidate()) def update_range_member_cache(sender, instance, **kwargs): for r in Range.objects.all(): r.increment_cache_version() # Invalidate range cache when it's data changes m2m_changed.connect(increment_range_cache_version, sender=Range.included_products.through) m2m_changed.connect(increment_range_cache_version, sender=Range.excluded_products.through) m2m_changed.connect(increment_range_cache_version, sender=Range.classes.through) m2m_changed.connect(increment_range_cache_version, sender=Range.included_categories.through) # Update range member cache when a product/category is saved post_save.connect(update_range_member_cache, sender=ProductCategory) post_save.connect(update_range_member_cache, sender=Product) # Invalidate cosmetic price cache whenever any Offer data changes post_save.connect(invalidate_pricing_cache_ns, sender=OfferGroup) post_save.connect(invalidate_pricing_cache_ns, sender=ConditionalOffer) post_save.connect(invalidate_pricing_cache_ns, sender=Benefit) post_save.connect(invalidate_pricing_cache_ns, sender=Condition) # Invalidate cosmetic price cache whenever any Product Range data changes
objects = CartManager() def __str__(self): return str(self.id) def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs): if action == "post_add" or action == "post_remove" or action == "post_clear": # print(action) # print(instance.product.all()) # print(instance.total) product = instance.product.all() total = 0 for x in product: total += x.price if instance.subtotal != total: #print(total) instance.subtotal = total instance.save() m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.product.through) def pre_save_cart_receiver(sender, instance, *args, **kwargs): if instance.subtotal > 0: instance.total = instance.subtotal + 10 #* 1.08 else: instance.total = 0.00 pre_save.connect(pre_save_cart_receiver, sender = Cart)
faculty.save() def create_faculty_profile(sender, instance, created, **kwargs): if instance.groups.filter(name="teacher").count(): create_faculty(instance) def create_faculty_profile_m2m(sender, instance, action, reverse, model, pk_set, **kwargs): if action == 'post_add' and instance.groups.filter(name="teacher").count(): create_faculty(instance) post_save.connect(create_faculty_profile, sender=User) m2m_changed.connect(create_faculty_profile_m2m, sender=User.groups.through) class UserPreference(models.Model): """ User Preferences """ file_format_choices = ( ('o', 'Open Document Format (.odt, .ods)'), ('m', 'Microsoft Binary (.doc, .xls)'), ('x', 'Microsoft Office Open XML (.docx, .xlsx) Not recommended, formatting may be lost!' ), ) prefered_file_format = models.CharField( default=settings.PREFERED_FORMAT, max_length="1", choices=file_format_choices,
total = models.DecimalField(decimal_places=2, max_digits=7, default=0.00) updated = models.DateTimeField(auto_now=True) timestamp = models.DateTimeField(auto_now_add=True) objects = CartManager() # check for product manyToMany Changes and update cart total def m2m_cart_reciever(sender, instance, action, *args, **kwargs): if action == 'post_add' or action == 'post_remove' or action == 'post_clear': total = 0 for product in instance.products.all(): total += product.price print(total) instance.subtotal = total instance.save() m2m_changed.connect(m2m_cart_reciever, sender=Cart.products.through) # update total when cart presave def pre_save_cart(sender, instance, *args, **kwargs): if instance.subtotal > 0: instance.total = instance.subtotal + 10 else: instance.total = 0.00 pre_save.connect(pre_save_cart, sender=Cart)
for email, ident in cls.objects.filter(services__in=services)\ .values_list('email', 'ident')\ .distinct(): # send email body = SUBSCRIPTION_EMAIL_TEMPLATE % dict( sub_url=urlparse.urljoin( conf.BASE_URL, reverse('overseer:update_subscription', args=[ident])), message=message, affects=affects, name=conf.NAME, ) send_mail('Status Change on %s' % conf.NAME, body, conf.FROM_EMAIL, [email], fail_silently=True) class UnverifiedSubscription(BaseSubscription): """ A temporary store for unverified subscriptions. """ email = models.EmailField() post_save.connect(Service.handle_event_save, sender=Event) post_save.connect(Event.handle_update_save, sender=EventUpdate) m2m_changed.connect(Service.handle_event_m2m_save, sender=Event.services.through) post_save.connect(Subscription.handle_update_save, sender=EventUpdate)
m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.inventory_sources.through) post_save.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource) post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=InventorySource) post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Job) post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Job) connect_computed_field_signals() post_save.connect(emit_job_event_detail, sender=JobEvent) post_save.connect(emit_ad_hoc_command_event_detail, sender=AdHocCommandEvent) m2m_changed.connect(rebuild_role_ancestor_list, Role.parents.through) m2m_changed.connect(org_admin_edit_members, Role.members.through) m2m_changed.connect(rbac_activity_stream, Role.members.through) m2m_changed.connect(rbac_activity_stream, Role.parents.through) post_save.connect(sync_superuser_status_to_rbac, sender=User) post_save.connect(create_user_role, sender=User) pre_delete.connect(cleanup_detached_labels_on_deleted_parent, sender=UnifiedJob) pre_delete.connect(cleanup_detached_labels_on_deleted_parent, sender=UnifiedJobTemplate) # Migrate hosts, groups to parent group(s) whenever a group is deleted @receiver(pre_delete, sender=Group) def save_related_pks_before_group_delete(sender, **kwargs):
order.save() def saveOrder(sender,instance,**kwargs): try: order=Order.objects.get(user=instance.user) except Order.DoesNotExist: pass else: updateTotal(order) pre_delete.connect(deleteOrder,sender=Order) #Before you delete the order delete all items associated with it post_save.connect(saveOrder,sender=OrderItem)#After saving an Orderitem update the order total post_delete.connect(saveOrder,sender=OrderItem)#After deleting an OrderItem update the total m2m_changed.connect(OrderItemChanged,sender=Order.items.through)#IF an item has been added or removed to my order, update the total class CaoruselImages(models.Model): CaoruselImage=models.ImageField(upload_to="Carousel_Images") def get_img_url(self): return self.CaoruselImage.url def __str__(self): return f'Caorusel Image {self.id}' class CategoryInfo(models.Model): CategoryImages=models.ImageField(upload_to="Category_Images") category=models.CharField(max_length=15,choices=category_choices,default='ADD SOON')
max_digits=100, decimal_places=2) timestamp = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) objects = CartManager() def __str__(self): return str(self.id) def cart_m2m_changed_save_receiver(sender, instance, action, *args, **kwargs): if action in ['post_add', 'post_remove', 'post_clear']: products = instance.products.all() total = sum([x.price for x in products]) if instance.subtotal != total: instance.subtotal = total instance.save() def cart_pre_save_receiver(sender, instance, *args, **kwargs): if instance.subtotal > 0: instance.total = instance.subtotal + 20 else: instance.total = 0 pre_save.connect(cart_pre_save_receiver, sender=Cart) m2m_changed.connect(cart_m2m_changed_save_receiver, sender=Cart.products.through)
instance.costList = [] for i in instance.food.all(): instance.costList.append(i.pricePerQuantity * int(instance.quantity[count])) cost = cost + (i.pricePerQuantity * int(instance.quantity[count])) count = count + 1 instance.totalCost = cost instance.save() def orderConfirmed(sender, instance, created, **kwargs): if (instance.order_status == '2'): broadcast_to_socket(instance) m2m_changed.connect(newOrderCreated, sender=Orders.food.through) post_save.connect(orderConfirmed, sender=Orders) def editFood(request, key): obj = Food.objects.get(pk=key) if request.method == 'POST': form = editFoodForm(request.POST, instance=obj) if form.is_valid: form.save() messages.success(request, f'Food Item updated successfully!') return redirect('viewMenu') else: messages.warning(request, f'Invalid input') else: form = editFoodForm(instance=obj)
# garantee that student has been subscribe in only one class if action == 'post_add': try: for student in instance.students.all(): classes = student.classes.filter( course=instance.course).exclude(id=instance.id) for classe in classes: student.classes.remove(classe) # garantee that this block executes only when instance == Class. except AttributeError: pass m2m_changed.connect(remove_duplicate_classes, sender=Class.students.through) class Course(models.Model): STATES = ( ('draft', _('Draft')), ('published', _('Published')), ) slug = models.SlugField(_('Slug'), max_length=255, unique=True) name = models.CharField(_('Name'), max_length=255, blank=True) intro_video = models.ForeignKey(Video, verbose_name=_('Intro video'), null=True, blank=True) application = models.TextField(_('Application'), blank=True)
users = get_user_model().objects.filter(pk__in=kwargs['pk_set']) # Clear the user's 'owned_groups' cache for user in users: cache.delete(user.cache_key + 'owned_groups') # Make sure group owners can direct message all other users if kwargs['action'] == 'post_add': direct_message_permission = Permission.objects.get( codename='can_initiate_direct_messages', content_type__app_label='accounts') for user in users: user.user_permissions.add(direct_message_permission) m2m_changed.connect(group_owners_changed, Group.owners.through) class GroupRequestManager(models.Manager): """Manager for GroupRequest.""" def unapproved(self): """Get unapproved requests.""" return super(GroupRequestManager, self).get_queryset().filter(moderated_by__isnull=True) class GroupRequest(TimestampModel): """GroupRequest model.""" user = models.ForeignKey(settings.AUTH_USER_MODEL) group = models.ForeignKey(Group) moderated_by = models.ForeignKey(settings.AUTH_USER_MODEL,
def _attach_signals(live_model): post_save.connect(save_copy_post_save, live_model) for field in live_model._meta.many_to_many: through_model = getattr(live_model, field.name).through m2m_changed.connect(on_m2m_change, sender=through_model)
# raw_ext = os.path.splitext(instance.raw_file.path)[1] # new_raw_filename = get_formatted_filename(instance.get_person(), instance.title, instance.date.year, raw_ext) # def get_formatted_filename(person, title_str, year, ext): # initial_path = instance.pdf_file.path # person = instance.get_person() # name = person.last_name # year = instance.date.year # title = instance.title.title() # title = ''.join(x for x in title if not x.isspace()) # title = ''.join(e for e in title if e.isalnum()) # # # change the pdf_file path to point to the renamed file # instance.pdf_file.name = os.path.join(dir_name, name + '_' + title + '_' + str(year) + '.pdf') # new_path = os.path.join(settings.MEDIA_ROOT, instance.pdf_file.name) # os.rename(initial_path, new_path) # instance.save() m2m_changed.connect(update_file_name_talks, sender=Talk.speakers.through) @receiver(post_delete, sender=Talk) def talk_delete(sender, instance, **kwargs): if instance.pdf_file: instance.pdf_file.delete(True) if instance.raw_file: instance.raw_file.delete(True) if instance.thumbnail: instance.thumbnail.delete(True)
associated ``EncodeProfile``s. """ from .tasks import encode_media, upload_media if not profiles: profiles = list(self.profiles.values_list('pk', flat=True)) for profile_id in profiles: (encode_media.s(self.id, profile_id) | upload_media.s(self.id, profile_id)).apply_async() def set_active(self): """ Set the media as active when it has been encoded into all associated ``EncodeProfile``s. Currently this is a one-way transition to prevent media from dropping in and out of the active set. """ if not self.active: storage_keys = set( self.remotestorage_set.values_list('profile', flat=True)) profile_keys = set(self.profiles.values_list('pk', flat=True)) if storage_keys == profile_keys: self.active = True self.save() pre_save.connect(set_encode_profiles, sender=Media) m2m_changed.connect(encode_profiles_changed, sender=Media.profiles.through) pre_delete.connect(delete_remote_storage, sender=Media)
objects = ThreadManager() class Meta: ordering = ['-updated'] # Buscar los mensajes que sí están en pk set y los borra de pk_set def messages_changed(sender, **kwargs): instance = kwargs.pop("instance", None) action = kwargs.pop("action", None) pk_set = kwargs.pop("pk_set", None) print(instance, action, pk_set) false_pk_set = set() if action is "pre_add": for msg_pk in pk_set: msg = Message.objects.get(pk=msg_pk) if msg.user not in instance.users.all(): print("Ups, ({}) no forma parte del hilo".format(msg.user)) false_pk_set.add(msg_pk) # Forzar la actualización haciendo save instance.save() # Borramos de pk_set los mensajes que concuerdan con los de false_pk_set pk_set.difference_update(false_pk_set) m2m_changed.connect(messages_changed, sender=Thread.messages.through)
decimal_places=2) total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2) updated = models.DateTimeField(auto_now=True) timestamp = models.DateTimeField(auto_now_add=True) objects = CartManager() def __str__(self): return str(self.id) def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs): if action == 'post_add' or action == 'post_remove' or action == 'post_clear': products = instance.products.all() total = 0 for x in products: total += x.price if instance.subtotal != total: instance.subtotal = total instance.save() m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through, weak=False) def pre_save_cart_receiver(sender, instance, *args, **kwargs): instance.total = instance.subtotal #*1.08 pre_save.connect(pre_save_cart_receiver, sender=Cart)
sub.date = datetime.datetime.utcnow().replace(tzinfo=utc) sub.save() # Increase the subscription count of the root. Post.objects.filter(pk=root.id).update(subs_count=F('subs_count') + 1) @staticmethod def finalize_delete(sender, instance, *args, **kwargs): # Decrease the subscription count of the post. Post.objects.filter(pk=instance.post.root_id).update( subs_count=F('subs_count') - 1) # Admin interface for subscriptions class SubscriptionAdmin(admin.ModelAdmin): search_fields = ('user__name', 'user__email') list_select_related = ["user", "post"] admin.site.register(Subscription, SubscriptionAdmin) # Data signals from django.db.models.signals import post_save, post_delete, m2m_changed post_save.connect(Post.check_root, sender=Post) post_save.connect(Subscription.create, sender=Post, dispatch_uid="create_subs") post_delete.connect(Subscription.finalize_delete, sender=Subscription, dispatch_uid="delete_subs") m2m_changed.connect(Tag.update_counts, sender=Post.tag_set.through)
class CardProducts(models.Model): cart = models.ForeignKey(Cart, on_delete=models.CASCADE) product = models.ForeignKey(Product, on_delete=models.CASCADE) quantity = models.IntegerField(default=1) created_at = models.DateTimeField(auto_now_add=True) objects = CartProductManager() def update_quantity(self, quantity=1): self.quantity = quantity self.save() def set_cart_id(sender, instance, *args, **kwargs): if not instance.cart_id: instance.cart_id = str(uuid.uuid4()) def update_totals(sender, instance, action, *args, **kwarg): if action == 'post_add' or action == 'post_remove' or action == 'post_clear': instance.update_totals() def post_save_update_totals(sender, instance, *args, **kwargs): instance.cart.update_totals() pre_save.connect(set_cart_id, sender=Cart) post_save.connect(post_save_update_totals, sender=CardProducts) m2m_changed.connect(update_totals, sender=Cart.products.through)
def __init__(self, *args, **kwargs): try: self._meta.get_field('status').default = get_default_status() except django.db.utils.ProgrammingError: pass return super(Poi, self).__init__(*args, **kwargs) def update_properties_cache(sender, instance, action, reverse, model, pk_set, **kwargs): "Property cache actualization at POI save. It will not work yet after property removal." if action == 'post_add': instance.save_properties_cache() m2m_changed.connect(update_properties_cache, Poi.properties.through) class GpxPoiForm(ModelForm): gpx_file = forms.FileField(required=False, help_text=_(u"Upload geometry by GPX file")) class Meta: model = Marker exclude = ('geom', ) def clean(self): cleaned_data = super(GpxPoiForm, self).clean() if 'gpx_file' in self.cleaned_data: gpx_file = self.cleaned_data['gpx_file'] if gpx_file:
return { 'handle': instance.handle, 'github_url': instance.github_url, 'local_avatar_url': instance.local_avatar_url, 'url': instance.get_relative_url() } @receiver(pre_save, sender=Tip, dispatch_uid="normalize_tip_usernames") def normalize_tip_usernames(sender, instance, **kwargs): """Handle pre-save signals from Tips to normalize Github usernames.""" if instance.username: instance.username = instance.username.replace("@", '') m2m_changed.connect(m2m_changed_interested, sender=Bounty.interested.through) # m2m_changed.connect(changed_fulfillments, sender=Bounty.fulfillments) class UserAction(SuperModel): """Records Actions that a user has taken .""" ACTION_TYPES = [ ('Login', 'Login'), ('Logout', 'Logout'), ] action = models.CharField(max_length=50, choices=ACTION_TYPES) profile = models.ForeignKey('dashboard.Profile', related_name='actions', on_delete=models.CASCADE) metadata = JSONField(default={})
**kwargs): """ Validates that a user is a friend before adding them to a FriendList. """ friendlist = instance if action == 'pre_add' and not reverse and model == User: friends = User.objects.filter(pk__in=pk_set) for friend in friends: if not Friendship.objects.are_friends(friendlist.owner, friend): raise ValidationError( "FriendList owner id %d is not friends with User id: %d" % (friendlist.id, friend.id)) m2m_changed.connect(only_add_friends, sender=FriendList.friends.through, dispatch_uid='validate_adding_friends') def remove_deleted_friendships_from_list(sender, instance, **kwargs): """ When a friendship is deleted, remove each user from each other's lists. """ user1 = instance.from_user user2 = instance.to_user for user, other_user in [(user1, user2), (user2, user1)]: lists = FriendList.objects.filter(owner=user) for l in lists: l.friends.remove(other_user)
kwargs.get('instance'), username)) def user_groups_changed(sender, **kwargs): group_map = {1: 'Moderators', 2: 'Editors'} action_map = {'post_add': 'added', 'post_remove': 'removed'} if kwargs.get('action').split('_')[0] == 'post': for index in kwargs.get('pk_set'): action = 'to' if kwargs.get('action').split( '_')[1] == 'add' else 'from' logger.info("User change: User {0} was {1} {2} group {3}".format( kwargs.get('instance').get_username(), action_map[kwargs.get('action')], action, group_map[index])) m2m_changed.connect(user_groups_changed, sender=User.groups.through) class HomePage(ContentPage, UniqueModel): """Unique home page.""" @property def content_section(self): return '' class Author(models.Model): name = models.CharField(max_length=255) title = models.CharField(max_length=255, blank=True) email = models.EmailField(blank=True) photo = models.ForeignKey('wagtailimages.Image', blank=True,
comments = models.ManyToManyField(Comment, blank=True) average_rating = models.DecimalField(default=0.00, max_digits=9, decimal_places=1) objects = ProductManager() def get_absolute_url(self): return f'product/{self.slug}' def __str__(self): return self.name def product_pre_save_receiver(sender, instance, *args, **kwargs): if instance.slug is None: instance.slug = unique_slug_generator(instance) pre_save.connect(product_pre_save_receiver, sender=Product) def average_rating_func(sender, instance, action, *args, **kwargs): if action == 'post_add' or action == 'post_remove' or action == 'post_clear': all_comments = instance.comments.all() total = 0 for i in all_comments: total += i.rating instance.average_rating = total/all_comments.count() instance.save() m2m_changed.connect(average_rating_func, sender=Product.comments.through)
try: clusters_to_refresh_set = diff_clusters_set.difference( instance.refreshed_clusters) except AttributeError: clusters_to_refresh_set = diff_clusters_set return list(clusters_to_refresh_set.intersection(set(all_clusters))) except (AttributeError, TypeError): return all_clusters def mark_cluster_as_refreshed(director, clusters): try: director.refreshed_clusters |= set(clusters) except AttributeError: director.refreshed_clusters = set(clusters) def reset_refreshed_clusters(director): director.refreshed_clusters = set() def is_only_cluster_update(instance): try: return set(instance.new_data.keys()) == {'cluster'} except AttributeError: return False m2m_changed.connect(model_update, sender=Director.cluster.through) m2m_changed.connect(model_update, sender=Route.clusters.through)
def __str__(self): return str(self.id) def pre_save_cart(sender,instance,action,*args,**kwargs): if action== 'post_add' or action =='post_remove' or action=='post_clear': products=instance.products.all() print(products) count=0 total=0 for product in products: total=total+product.price count=count+1 instance.subtotal=total instance.total_count=count instance.save() m2m_changed.connect(pre_save_cart,sender=Cart.products.through) def pre_save_cart_add(sender,instance,*args,**kwargs): if instance.subtotal>0: instance.total_price=instance.subtotal+40 else: instance.total_price=0.00 pre_save.connect(pre_save_cart_add,sender=Cart)
}) yield SimpleHelpBlock(text=_("Add a product to see it in your store"), actions=actions, icon_url="shuup_admin/img/product.png", priority=0, category=HelpBlockCategory.PRODUCTS, done=Product.objects.filter( shop_products__shop=request.shop).exists() if kind == "setup" else False) def get_required_permissions(self): return (get_permissions_from_urls(self.get_urls()) | get_default_model_permissions(Product) | get_default_model_permissions(File)) def get_model_url(self, object, kind, shop=None): if isinstance(object, Product): object = object.get_shop_instance(shop) return derive_model_url(ShopProduct, "shuup_admin:shop_product", object, kind) m2m_changed.connect(update_categories_through, sender=ShopProduct.categories.through, dispatch_uid="shop_product:update_categories_through") post_save.connect(update_categories_post_save, sender=ShopProduct, dispatch_uid="shop_product:update_categories")
def update_rb_review_group(sender, instance, created, **kwargs): course = instance logger.info("update_rb_review_group: '%s'", course) if not course.is_rb_integrated(): return rb_review_group_name = "teachers_{0}".format(course.id) rg = RbReviewGroup(rb_review_group_name) rg.create() teachers = set([teacher.username for teacher in course.teachers.all()]) rg_users = set(rg.list()) logger.info("Course: '%s', teachets '%s', rg_users '%s'", course, teachers, rg_users) for rg_user in rg_users: if rg_user not in teachers: logger.info("Course: '%s', user_del '%s'", course, rg_user) rg.user_del(rg_user) for teacher in teachers: if teacher not in rg_users: logger.info("Course: '%s', user_add '%s'", course, teacher) rg.user_add(teacher) m2m_changed.connect(add_default_issue_fields, sender=Course.issue_fields.through) post_save.connect(update_rb_review_group, sender=Course)
timestamp = models.DateTimeField(auto_now_add=True) objects = BookManager() def __str__(self): return str(self.id) def m2m_changed_book_receiver(sender, instance, action, *args, **kwargs): if action == 'post_add' or action == 'post_remove' or action == 'post_clear': products = instance.products.all() total = 0 for x in products: total += x.price if instance.subtotal != total: instance.subtotal = total instance.save() m2m_changed.connect(m2m_changed_book_receiver, sender=Book.products.through) def pre_save_book_receiver(sender, instance, *args, **kwargs): if instance.subtotal > 0: instance.total = Decimal(instance.subtotal) * Decimal(1.08) # 8% tax else: instance.total = 0.00 pre_save.connect(pre_save_book_receiver, sender=Book)
meeting = kwargs['instance'] for mk_id in kwargs['pk_set']: m = Member.objects.get(pk=mk_id) if Action.objects.filter(actor_object_id=m.id, actor_content_type=member_ct, verb='attended', target_object_id=meeting.id, target_content_type=cm_ct).count() == 0: action.send(m, verb='attended', target=meeting, description='committee meeting', timestamp=meeting.date) m2m_changed.connect(record_committee_presence, sender=CommitteeMeeting.mks_attended.through) @disable_for_loaddata def handle_annotation_save(sender, created, instance, **kwargs): if created: action.send(instance.content_object.meeting, verb='annotation-added', target=instance, description=unicode(instance.flag_value)) action.send(instance.user, verb='annotated', target=instance, description=unicode(instance.flag_value)) follow(instance.user, instance.content_object.meeting)