def update(self, using=None, **kwargs): """ Updates specified attributes on the current instance. """ assert self.pk, "Cannot update an instance that has not yet been created." using = using or router.db_for_write(self.__class__, instance=self) for field in self._meta.fields: if getattr(field, 'auto_now', False) and field.name not in kwargs: kwargs[field.name] = field.pre_save(self, False) affected = self.__class__._base_manager.using(using).filter(pk=self.pk).update(**kwargs) for k, v in six.iteritems(kwargs): if isinstance(v, ExpressionNode): v = resolve_expression_node(self, v) setattr(self, k, v) if affected == 1: post_save.send(sender=self.__class__, instance=self, created=False) return affected elif affected == 0: return affected elif affected < 0: raise ValueError("Somehow we have updated a negative amount of rows, you seem to have a problem with your db backend.") else: raise ValueError("Somehow we have updated multiple rows, and you are now royally f****d.")
def add_members_to_current_portal(self, request, queryset, remove_all_other_memberships=False): """ Converts this CosinnusGroup's type """ member_names = [] members = [] for group in queryset: group.clear_member_cache() members.extend(group.members) members = list(set(members)) users = get_user_model().objects.filter(id__in=members) if remove_all_other_memberships: # delete all other portal memberships because users were supposed to be moved CosinnusPortalMembership.objects.filter(user__in=users).delete() else: # just add them, that means that pending statuses will be removed to be replaced by members statuses in a second CosinnusPortalMembership.objects.filter(status=MEMBERSHIP_PENDING, group=CosinnusPortal.get_current(), user__in=users).delete() for user in users: membership, created = CosinnusPortalMembership.objects.get_or_create(group=CosinnusPortal.get_current(), user=user, defaults={'status': MEMBERSHIP_MEMBER}) # this ensures that join-signals for all members really arrive (for putting new portal members into the Blog, etc) post_save.send(sender=CosinnusPortalMembership, instance=membership, created=True) member_names.append('%s %s (%s)' % (user.first_name, user.last_name, user.email)) if member_names: message = _('The following Users were added to this portal:') + '\n' + ", ".join(member_names) self.message_user(request, message)
def bulk_create_with_signal(cls: models.Model, items, **kwargs): for i in items: pre_save.send(sender=cls, instance=i) result = cls.objects.bulk_create(items, **kwargs) for i in items: post_save.send(sender=cls, instance=i, created=True) return result
def method_save_new(instance, *args, **kwargs): if instance.pk: return self.method_save_original(instance, *args, **kwargs) else: # Set meta.auto_created to True to have the original save_base # not send the pre_save signal which would normally send # the instance without a primary key. Since we assign a random # primary key any pre_save signal handler that relies on an # empty primary key will fail. # The meta.auto_created and manual pre_save sending emulates # the original behavior. Since meta.auto_created also disables # the post_save signal we must also send it ourselves. # This hack work with Django 1.11 .save_base() but can break # in future versions if that method is updated. pre_save.send( sender=instance.__class__, instance=instance, raw=False, update_fields=None, ) instance._meta.auto_created = True instance.pk = RandomPrimaryKeyModelMonkeyPatchMixin.get_unique_primary_key( model=instance._meta.model ) instance.id = instance.pk result = instance.save_base(force_insert=True) instance._meta.auto_created = False post_save.send( sender=instance.__class__, instance=instance, created=True, update_fields=None, raw=False ) return result
def handle_update_save(cls, instance, created, **kwargs): event = instance.event if created: is_latest = True elif EventUpdate.objects.filter(event=event).order_by('-date_created')\ .values_list('event', flat=True)[0] == event.pk: is_latest = True else: is_latest = False if is_latest: update_kwargs = dict( status=instance.status, date_updated=instance.date_created, message=instance.message ) if not event.description: update_kwargs['description'] = instance.message if not event.peak_status or event.peak_status < instance.status: update_kwargs['peak_status'] = instance.status Event.objects.filter(pk=event.pk).update(**update_kwargs) for k, v in update_kwargs.iteritems(): setattr(event, k, v) # Without sending the signal Service will fail to update post_save.send(sender=Event, instance=event, created=False)
def test_is_expired_after_config_saved(self): """Testing IntegrationManager.is_expired after config saved""" manager = IntegrationManager(IntegrationConfig) self.assertFalse(manager.is_expired()) post_save.send(sender=IntegrationConfig) self.assertTrue(manager.is_expired())
def handle_update_save(cls, instance, created, **kwargs): event = instance.event if created: is_latest = True elif EventUpdate.objects.filter(event=event).order_by('-date_created')\ .values_list('event', flat=True)[0] == event.pk: is_latest = True else: is_latest = False if is_latest: update_kwargs = dict(status=instance.status, date_updated=instance.date_created, message=instance.message) if not event.description: update_kwargs['description'] = instance.message if not event.peak_status or event.peak_status < instance.status: update_kwargs['peak_status'] = instance.status Event.objects.filter(pk=event.pk).update(**update_kwargs) for k, v in update_kwargs.iteritems(): setattr(event, k, v) # Without sending the signal Service will fail to update post_save.send(sender=Event, instance=event, created=False)
def add_participants(self, request, *participants_ids): """ Ensures the current user has the authorization to add the participants. By default, a user can add a participant if he himself is a participant. A callback can be added in the settings here. """ participants_ids_returned_by_callback = getattr( settings, 'REST_MESSAGING_ADD_PARTICIPANTS_CALLBACK', self._limit_participants)(request, *participants_ids) participations = [] ids = [] for participant_id in participants_ids_returned_by_callback: participations.append( Participation(participant_id=participant_id, thread=self)) ids.append(participant_id) Participation.objects.bulk_create(participations) post_save.send( Thread, instance=self, created=True, created_and_add_participants=True, request_participant_id=request.rest_messaging_participant.id) return ids
def test_model_save(self): """Test signal handling for when Discord user model objects are saved to DB.""" mock_obj = mock.Mock() with mock.patch.object(AllauthSignalListener, "_apply_groups", mock_obj): AllauthSignalListener() post_save.send( DiscordUser, instance=self.discord_user, raw=True, created=None, # Not realistic, but we don't use it using=None, # Again, we don't use it update_fields=False # Always false during integration testing ) mock_obj.assert_not_called() post_save.send( DiscordUser, instance=self.discord_user, raw=False, created=None, # Not realistic, but we don't use it using=None, # Again, we don't use it update_fields=False # Always false during integration testing ) mock_obj.assert_called_with(self.discord_user, self.social_user)
def update(self, using=None, **kwargs): """ Updates specified attributes on the current instance. """ assert self.pk, "Cannot update an instance that has not yet been created." using = using or router.db_for_write(self.__class__, instance=self) for field in self._meta.fields: if getattr(field, "auto_now", False) and field.name not in kwargs: kwargs[field.name] = field.pre_save(self, False) affected = self.__class__._base_manager.using(using).filter( pk=self.pk).update(**kwargs) for k, v in six.iteritems(kwargs): if isinstance(v, CombinedExpression): v = resolve_combined_expression(self, v) setattr(self, k, v) if affected == 1: post_save.send(sender=self.__class__, instance=self, created=False) return affected elif affected == 0: return affected elif affected < 0: raise ValueError( "Somehow we have updated a negative amount of rows, you seem to have a problem with your db backend." ) else: raise ValueError( "Somehow we have updated multiple rows, and you are now royally f****d." )
def handle(self, *args, **options): logging.getLogger().handlers[0].level = logging.ERROR for document in tqdm.tqdm(Document.objects.all(), disable=options['no_progress_bar']): post_save.send(Document, instance=document)
def claimed_ticket_completed(sender, **kwargs): """A ticket that a mentor claimed was completed""" instance = kwargs['instance'] if not instance.state == "completed": return self = instance.claimer.mentor post_save.send(Mentor, instance=self, created=False)
def update(instance: Model, using: str | None = None, **kwargs: Any) -> int: """ Updates specified attributes on the current instance. """ assert instance.pk, "Cannot update an instance that has not yet been created." using = using or router.db_for_write(instance.__class__, instance=instance) for field in instance._meta.fields: if getattr(field, "auto_now", False) and field.name not in kwargs: kwargs[field.name] = field.pre_save(instance, False) affected = cast( int, instance.__class__._base_manager.using(using).filter(pk=instance.pk).update(**kwargs) ) for k, v in kwargs.items(): setattr(instance, k, _handle_value(instance, v)) if affected == 1: post_save.send(sender=instance.__class__, instance=instance, created=False) return affected elif affected == 0: return affected elif affected < 0: raise ValueError( "Somehow we have updated a negative number of rows. You seem to have a problem with your db backend." ) else: raise ValueError("Somehow we have updated multiple rows. This is very, very bad.")
def add_participants(self, request, *participants_ids): """ Ensures the current user has the authorization to add the participants. By default, a user can add a participant if he himself is a participant. A callback can be added in the settings here. """ participants_ids_returned_by_callback = getattr( settings, "REST_MESSAGING_ADD_PARTICIPANTS_CALLBACK", self._limit_participants )(request, *participants_ids) participations = [] ids = [] for participant_id in participants_ids_returned_by_callback: participations.append(Participation(participant_id=participant_id, thread=self)) ids.append(participant_id) Participation.objects.bulk_create(participations) post_save.send( Thread, instance=self, created=True, created_and_add_participants=True, request_participant_id=request.rest_messaging_participant.id, ) return ids
def form_valid(self, form): """Trigger post-save signal for all users to sync group leader roles""" users = User.objects.all() for user in users: post_save.send(User, instance=user) return HttpResponseRedirect(self.get_success_url())
def init_historical_records_from_model(model, is_m2m=False): from . import models as historical_models from django.db import models real_instances = model.objects.all() real_instance_fields = [f.name for f in model._meta.fields] for real_instance in real_instances: query_list = [] for field in real_instance_fields: query_list.append(Q(**{field: getattr(real_instance, field)})) query = reduce(lambda x, y: x & y, query_list, Q()) if historical_models.registered_historical_models[ model.__name__].objects.filter(query).exists(): continue else: if is_m2m: attrs = [] for field in model._meta.fields: if isinstance(field, models.ForeignKey): attrs.append(field) if attrs.__len__() == 2: break m2m_changed.send(model, instance=getattr(real_instance, attrs[0].name), model=attrs[1].rel.to, action='post_add') else: post_save.send(model, instance=real_instance, created=True, weak=False)
def fake_save(self, instance): cls = instance.__class__ pre_save.send(sender=cls, instance=instance) for field in cls._meta.fields: if isinstance(field, FileField): getattr(instance, field.name)._committed = True post_save.send(sender=cls, instance=instance) return self.storage.listdir('avatars')[1]
def test_ensure_profile_handles_signal(self): george = User(username='******', is_staff=True) george.has_perm = Mock() george.has_perm.return_value = True with self.assertRaises(ValueError): # post_save must raise, since John was not saved, so save() on # related Profile is prohibited to prevent data loss. post_save.send(sender=george.__class__, instance=george)
def handle(self, *args, **options): self.verbosity = options["verbosity"] logging.getLogger().handlers[0].level = logging.ERROR for document in tqdm.tqdm(Document.objects.all()): post_save.send(Document, instance=document)
def test_post_save_unchanged(self): with must_be_called(False) as func: post_save_changed.connect(func, sender=FakeModel) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) # This *doesn't* call post_save_changed, because we haven't changed anything. post_save.send(instance=obj, sender=FakeModel)
def bulk_create(self, objs, **kwargs): returned = super(MotivationManager, self).bulk_create(objs, **kwargs) for obj in objs: post_save.send(sender=obj.__class__, instance=obj, created=True, using=None) return returned
def on_model_post_create(self, model, instance): model_cls, django_instance = self.get_django_instance(model, instance) post_save.send(model_cls, raw=True, using=self, instance=django_instance, created=True, update_fields=[])
def test_post_save_with_fields_unchanged(self): with must_be_called(False) as func: post_save_changed.connect(func, sender=FakeModel, fields=('a_key',)) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) obj.another = 'dont care about this field' post_save.send(instance=obj, sender=FakeModel)
def test_post_save_with_fields_changed(self): with must_be_called(True) as func: post_save_changed.connect(func, sender=FakeModel, fields=('a_key',)) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) obj.a_key = 'change a field that we care about' post_save.send(instance=obj, sender=FakeModel)
def test_post_save_changed(self): with must_be_called(True) as func: post_save_changed.connect(func, sender=FakeModel) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) obj.a_key = 'another value' post_save.send(instance=obj, sender=FakeModel)
def update_voteable_metrics_from_vote(sender, **kwargs): """ Update vote metrics (acceptance and impact) and save to DB. """ vote = kwargs.get('instance') if vote and vote.voteable: voteable = vote.voteable voteable.acceptance = voteable.get_acceptance() type(voteable).objects.filter(pk=voteable.pk).update( acceptance=voteable.acceptance) post_save.send(type(voteable), instance=voteable)
def set_attrs(self, d): ''' Set node attributes according to the provided dictionary. TODO: Replace by true bulk insert implementation. ''' for key, value in d.iteritems(): self.set_attr(key, value) post_save.send(sender=self.__class__, instance=self)
def ws_message(message): # Target id from pushed list id = json.loads(message.content['text'])['id'] # Subscribe client to Target's channel Group('url-{}'.format(id)).add(message.reply_channel) instance = models.Target.objects.get(id=id) # Format Target's fields and push to client post_save.send(models.Target, instance=instance, created=False)
def test_language_delete(self): language = self.exec_without_signals( lambda: Language.objects.create(name='PHP')) post_save.send(Language, instance=language, created=True) self.exec_without_signals(lambda: language.delete()) self.assertEqual(Language.objects.count(), 0) self.assertEqual(User.objects.count(), 0) self.assertEqual(Repository.objects.count(), 0)
def create_post(self, author, country, city, image = None, image_1=None, image_2=None, image_3=None, text = None): try: post = self.create(author=author, country= country, city=city, image=image, image_1=image_1, image_2=image_2, image_3=image_3, text=text) print('post created') post_save.send(sender = self.__class__, instance = post) print('save signal sent') return post except: print('save signal not sent, returning None') return None
def update_object(obj, reload=False, signal=True, **kwargs): updated = obj.__class__.objects.filter(pk=obj.pk).update(**kwargs) > 0 if reload: reload_object(obj) else: for k, v in kwargs.items(): setattr(obj, k, v) if updated and signal: post_save.send(sender=obj.__class__, instance=obj, created=False) return updated
def remove_participant(self, request, participant): removable_participants_ids = self.get_removable_participants_ids(request) if participant.id in removable_participants_ids: participation = Participation.objects.get(participant=participant, thread=self, date_left=None) participation.date_left = now() participation.save() post_save.send(Thread, instance=self, created=False, remove_participant=True, removed_participant=participant, request_participant_id=request.rest_messaging_participant.id) return participation else: raise Exception('The participant may not be removed.')
def create(mobile, channel_id, name): mob = adapt_mobile(mobile) item, created = Subscriber.objects.get_or_create(mobile = mob) item.name = name item.save() ch = Channel.objects.get(pk = channel_id) if ch not in item.channels.all(): item.channels.add(ch) item.save() post_save.send(sender=Subscriber, instance=item) return created
def test_post_save_with_fields_changed(self): with must_be_called(True) as func: post_save_changed.connect(func, sender=FakeModel, fields=('a_key', )) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) obj.a_key = 'change a field that we care about' post_save.send(instance=obj, sender=FakeModel)
def update_instrument(self, instance, old_value): if instance is not None and instance.instrument is not None: post_save.send(sender=Instrument, instance=instance.instrument, in_real_signal=True) if old_value is not None: instru = Instrument.objects.get(id=old_value) if not isinstance( old_value, Instrument) else old_value nb = instru.performances.count() if nb == 0: post_delete.send(sender=Instrument, instance=instru)
def save_dirty(self, raw=False, using=None): """ An alternative to save, instead writing every field again, only updates the dirty fields via QuerySet.update """ if not self.pk: self.save(using=using) updated = 1 else: # a lot copied from django/db/models/base.py using = using or router.db_for_write(self.__class__, instance=self) changed_values = self.get_changed_values() if len(changed_values.keys()) == 0: return False pre_save.send(sender=self.__class__, instance=self, raw=raw, using=using) # Detect if updating relationship field_ids directly # If related field object itself has changed then the field_id # also changes, in which case we detect and ignore the field_id # change, otherwise we'll reload the object again later unnecessarily rel_fields = {f.column: f for f in self._meta.fields if f.rel} updated_rel_ids = [] for field_name in changed_values.keys(): if field_name in rel_fields.keys(): rel_field = rel_fields[field_name] value = changed_values[rel_field.column] obj_value = getattr(self, rel_field.name).pk del changed_values[rel_field.column] changed_values[rel_field.name] = value if value != obj_value: updated_rel_ids.append(rel_field.column) # Maps db column names back to field names if they differ field_map = {f.column: f.name for f in self._meta.fields if f.db_column} for field_from, field_to in field_map.iteritems(): if field_from in changed_values: changed_values[field_to] = changed_values[field_from] del changed_values[field_from] updated = self.__class__.objects.filter(pk=self.pk).update(**changed_values) # Reload updated relationships for field_name in updated_rel_ids: field = rel_fields[field_name] field_pk = getattr(self, field_name) rel_obj = field.related.parent_model.objects.get(pk=field_pk) setattr(self, field.name, rel_obj) self._reset_state() post_save.send(sender=self.__class__, instance=self, created=False, raw=raw, using=using) return updated == 1
def test_post_save_with_fields_unchanged(self): with must_be_called(False) as func: post_save_changed.connect(func, sender=FakeModel, fields=('a_key', )) obj = FakeModel() post_init.send(instance=obj, sender=FakeModel) obj.another = 'dont care about this field' post_save.send(instance=obj, sender=FakeModel)
def create(cls, **kwargs): result = super().create(**kwargs) post_save.send( sender=cls, instance=result, created=True, raw=False, ) return result
def bulk_create(self, objs, batch_size: Optional[int] = None, ignore_conflicts: bool = False): objs = list(objs) # If not it won't be iterate later result = super().bulk_create(objs, batch_size=batch_size, ignore_conflicts=ignore_conflicts) for obj in objs: post_save.send(obj.__class__, instance=obj, created=True) return result
def save(self, force_insert=False, force_update=False): if not self.pk: self.last_reply = datetime.now() # set parent group group = BaseGroup.objects.get(id=self.object_id) self.parent_group = group self.visible = group.slug == 'ewb' super(GroupTopic, self).save(force_insert, force_update) post_save.send(sender=Topic, instance=GroupTopic.objects.get(id=self.id))
def bulk_update_documents(document_ids): documents = Document.objects.filter(id__in=document_ids) ix = index.open_index() for doc in documents: post_save.send(Document, instance=doc, created=False) with AsyncWriter(ix) as writer: for doc in documents: index.update_document(writer, doc)
def save(self, force_insert=False, force_update=False): # validate HTML content # Additional options at http://codespeak.net/lxml/lxmlhtml.html#cleaning-up-html self.body = clean_html(self.body) self.body = autolink_html(self.body) # set parent group group = BaseGroup.objects.get(id=self.object_id) self.parent_group = group super(GroupTopic, self).save(force_insert, force_update) post_save.send(sender=Topic, instance=GroupTopic.objects.get(id=self.id))
def update(self, **kwargs): for instance in self: pre_save.send(sender=instance.__class__, instance=instance, raw=False, using=self.db, update_fields=kwargs.keys()) result = super(UpdateSignalsQuerySet, self.all()).update(**kwargs) for instance in self: for key, value in kwargs.items(): # Fake setting off values from kwargs setattr(instance, key, value) post_save.send(sender=instance.__class__, instance=instance, created=False, raw=False, using=self.db, update_fields=kwargs.keys()) return result
def _move_item(self, request, startorder, endorder): if self._get_order_direction(request) != '-1': order_up, order_down = self.default_order_directions[0] else: order_up, order_down = self.default_order_directions[1] if startorder < endorder - order_up: finalorder = endorder - order_up move_filter = { '{0}__gte'.format(self.default_order_field): startorder, '{0}__lte'.format(self.default_order_field): finalorder, } order_by = self.default_order_field move_update = {self.default_order_field: F(self.default_order_field) - 1} elif startorder > endorder + order_down: finalorder = endorder + order_down move_filter = { '{0}__gte'.format(self.default_order_field): finalorder, '{0}__lte'.format(self.default_order_field): startorder, } order_by = '-{0}'.format(self.default_order_field) move_update = {self.default_order_field: F(self.default_order_field) + 1} else: return self.model.objects.none() with transaction.atomic(): extra_model_filters = self.get_extra_model_filters(request) filters = {self.default_order_field: startorder} filters.update(extra_model_filters) move_filter.update(extra_model_filters) obj = self.model.objects.get(**filters) obj_qs = self.model.objects.filter(pk=obj.pk) move_qs = self.model.objects.filter(**move_filter).order_by(order_by) for instance in move_qs: pre_save.send( self.model, instance=instance, update_fields=[self.default_order_field], raw=False, using=None or router.db_for_write( self.model, instance=instance), ) # using qs.update avoid multi [pre|post]_save signal on obj.save() obj_qs.update(**{self.default_order_field: self.get_max_order(request, obj) + 1}) move_qs.update(**move_update) obj_qs.update(**{self.default_order_field: finalorder}) for instance in move_qs: post_save.send(self.model, instance=instance, update_fields=[self.default_order_field]) query_set = self.model.objects.filter(**move_filter).order_by(self.default_order_field).values_list('pk', self.default_order_field) return [dict(pk=pk, order=order) for pk, order in query_set]
def save(self, objects, connection): """ Saves the objects to the given connection :param objects: the objects to save :param connection: the connection which should be used for saving the object :return: nothing, the objects are updated with the "id" property """ def _serialize_object(object_to_serialize): if object_to_serialize.is_incomplete: raise AttributeError( "Object %s is incomplete, probably obtained from search and can not be saved. " + "To get metadata-complete record, call .update() on the object" % object_to_serialize ) return { "metadata": object_to_serialize.metadata, "bitstream": object_to_serialize.get_local_bitstream(), "slug": object_to_serialize.slug, } objects_to_update = [] objects_to_create = [] if connection is None: connection = self.connection for o in objects: if o.objects_fedora_connection == connection and o.id: objects_to_update.append(o) pre_save.send(sender=o.__class__, instance=o, raw=False, using="repository", update_fields=None) else: objects_to_create.append(o) pre_save.send(sender=o.__class__, instance=o, raw=False, using="repository", update_fields=None) if objects_to_update: metadata = connection.update_objects([_serialize_object(o) for o in objects_to_update]) for md, obj in zip(metadata, objects_to_update): obj.metadata = md if objects_to_create: metadata = connection.create_objects([_serialize_object(o) for o in objects_to_create]) for md, obj in zip(metadata, objects_to_create): obj.metadata = md for o in objects: post_save.send( sender=o.__class__, instance=o, created=None, raw=False, using="repository", update_fields=None )
def update(self, **kwargs): """ Convert custom '__raw' flag to 'raw' flag from base_save. Call post_save signal on update. """ raw = kwargs.get('__raw', False) if raw: del kwargs['__raw'] super(KFTQuerySet, self).update(**kwargs) for instance in self._clone(): post_save.send( sender=self.model, instance=instance, raw=raw )
def record_vote(self, obj, user, vote): """ Record a user's vote on a given object. Only allows a given user to vote once, though that vote may be changed. A zero vote indicates that any existing vote should be removed. """ if vote not in (+1, -1): raise ValueError('Invalid vote (must be +1/0/-1)') ctype = ContentType.objects.get_for_model(obj) if self.filter(user=user, content_type=ctype, object_id=obj._get_pk_val()).exists(): return else: vote_obj = self.create(user=user, content_type=ctype, object_id=obj._get_pk_val(), vote=vote) post_save.send(sender=vote_obj, vote=vote_obj.vote)
def approve_benchmark(modeladmin, request, queryset): """ Action in Benchmark Admin that mark selected Benchmarks as Approved """ for benchmark in queryset: LogEntry.objects.log_action( user_id=request.user.pk, content_type_id=ContentType.objects.get_for_model(benchmark).pk, object_id=benchmark.pk, object_repr=force_unicode(benchmark), action_flag=CHANGE, change_message='Changed approved.' ) benchmark.approved = True post_save.send(sender=BenchmarkPending, instance=benchmark) queryset.update(approved=True)
def update_ancestor(sender, instance, **kwargs): if kwargs['created'] or not kwargs['update_fields'] or 'parent' in kwargs['update_fields']: ancestor_or_self = instance.recursive_ancestor_or_self() if instance.ancestor_or_self != ancestor_or_self: FundingInstitution.objects.filter(id=instance.id).update( ancestor_or_self=ancestor_or_self ) if not kwargs['raw']: for child in instance.fundinginstitution_set.all(): post_save.send( sender=sender, instance=child, raw=kwargs['raw'], created=kwargs['created'], using=kwargs['using'], update_fields=kwargs['update_fields'], )
def remove_participant(self, request, participant): removable_participants_ids = self.get_removable_participants_ids(request) if participant.id in removable_participants_ids: participation = Participation.objects.get(participant=participant, thread=self, date_left=None) participation.date_left = now() participation.save() post_save.send( Thread, instance=self, created=False, remove_participant=True, removed_participant=participant, request_participant_id=request.rest_messaging_participant.id, ) return participation else: raise Exception("The participant may not be removed.")
def test_clearable(self): """ A ClearablFileInput will set field value to False before pre_save """ profile = models.Profile(avatar='avatars/test.jpg') cls = profile.__class__ profile.avatar = False pre_save.send(sender=cls, instance=profile) # Saving will then properly clear profile.avatar = '' post_save.send(sender=cls, instance=profile) # FileField is cleared, but not explicitly deleted, file remains files = self.storage.listdir('avatars')[1] self.assertEqual(len(files), 1)
def update_solution_metrics_from_comment(sender, **kwargs): """ Update vote metrics for a solution when it's comment is updated. Because a rejected vote's validity depends on whether there is a comment. """ from solution.models import Solution # avoid circular import comment = kwargs.get('instance') solution_type = ContentType.objects.get_for_model(Solution) # todo check that comment is part of the commentable comment_set and not # outside of it if comment and comment.commentable_id \ and comment.commentable_type_id == solution_type.id: solution = comment.commentable solution.acceptance = solution.get_acceptance() Solution.objects.filter(pk=solution.pk).update( acceptance=solution.acceptance) post_save.send(Solution, instance=solution)
def get_or_create_thread(self, request, name=None, *participant_ids): """ When a Participant posts a message to other participants without specifying an existing Thread, we must 1. Create a new Thread if they have not yet opened the discussion. 2. If they have already opened the discussion and multiple Threads are not allowed for the same users, we must re-attach this message to the existing thread. 3. If they have already opened the discussion and multiple Threads are allowed, we simply create a new one. """ # we get the current participant # or create him if he does not exit participant_ids = list(participant_ids) if request.rest_messaging_participant.id not in participant_ids: participant_ids.append(request.rest_messaging_participant.id) # we need at least one other participant if len(participant_ids) < 2: raise Exception("At least two participants are required.") if getattr(settings, "REST_MESSAGING_THREAD_UNIQUE_FOR_ACTIVE_RECIPIENTS", True) is True: # if we limit the number of threads by active participants # we ensure a thread is not already running existing_threads = self.get_active_threads_involving_all_participants(*participant_ids) if len(list(existing_threads)) > 0: return existing_threads[0] # we have no existing Thread or multiple Thread instances are allowed thread = Thread.objects.create(name=name) # we add the participants thread.add_participants(request, *participant_ids) # we send a signal to say the thread with participants is created post_save.send( Thread, instance=thread, created=True, created_and_add_participants=True, request_participant_id=request.rest_messaging_participant.id, ) return thread