def remove(self, *objs, **kwargs): """ Remove the specified object from the M2M field. The object can be a real model instance or an ObjectId or a string representing an ObjectId. The related object is not deleted, it's only removed from the list. Only supported kwarg is 'auto_save' :param auto_save: See add() above for description """ auto_save = kwargs.pop('auto_save', True) obj_ids = set([ObjectId(obj) if isinstance(obj, (ObjectId, basestring)) else ObjectId(obj.pk) for obj in objs]) # Calculate list of object ids that will be removed removed_obj_ids = [str(obj['pk']) for obj in self.objects if obj['pk'] in obj_ids] # Send the pre_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) # Commit the remove self.objects = [obj for obj in self.objects if obj['pk'] not in obj_ids] # Send the post_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) if auto_save: self.model_instance.save()
def clear(self, auto_save=True): """ Clear all objects in the list. The related objects are not deleted from the database. :param auto_save: See add() above for description """ # Calculate list of object ids that will be removed removed_obj_ids = [str(obj['pk']) for obj in self.objects] # Send the pre_clear signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_clear', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) # Commit the clear self.objects = [] # Send the post_clear signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_clear', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) if auto_save: self.model_instance.save()
def add(self, *objs): """ Add model instance(s) to the M2M field. The objects can be real Model instances or just ObjectIds (or strings representing ObjectIds). """ using = 'default' # should see if we can carry this over from somewhere add_objs = [] for obj in objs: if isinstance(obj, (ObjectId, basestring)): # It's an ObjectId pk = ObjectId(obj) instance = None else: # It's a model object pk = ObjectId(obj.pk) instance = obj if not pk in (obj['pk'] for obj in self.objects): add_objs.append({'pk':pk, 'obj':instance}) # Calculate list of object ids that are being added add_obj_ids = [str(obj['pk']) for obj in add_objs] # Send pre_add signal (instance should be Through instance but it's the manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) # Commit the add for obj in add_objs: self.objects.append({'pk':obj['pk'], 'obj':obj['obj']}) # Send post_add signal (instance should be Through instance but it's the manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) return self
def on_asset_post_delete(instance: Asset, using, **kwargs): node_ids = getattr(instance, RELATED_NODE_IDS, None) if node_ids: m2m_changed.send( sender=Asset.nodes.through, instance=instance, reverse=False, model=Node, pk_set=node_ids, using=using, action=POST_REMOVE )
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 add(self, *objs, **kwargs): """ Add model instance(s) to the M2M field. The objects can be real Model instances or just ObjectIds (or strings representing ObjectIds). Only supported kwarg is 'auto_save' :param auto_save: Defaults to True. When a model is added to the M2M, the behavior of Django is to create an entry in the through-table, which essentially saves the list. In order to do the equivalent, we need to save the model. However, that behavior is not the same as Django either because Django doesn't save the whole model object, so that's why this is optional. Swings and Roundabouts. """ auto_save = kwargs.pop('auto_save', True) using = router.db_for_write( self.model_instance if self.model_instance else self.field.model) add_objs = [] for obj in objs: if isinstance(obj, (ObjectId, basestring)): # It's an ObjectId pk = ObjectId(obj) instance = None else: # It's a model object pk = ObjectId(obj.pk) instance = obj if not pk in (obj['pk'] for obj in self.objects): add_objs.append({'pk': pk, 'obj': instance}) # Calculate list of object ids that are being added add_obj_ids = [str(obj['pk']) for obj in add_objs] # Send pre_add signal (instance should be Through instance but it's the # manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) # Commit the add for obj in add_objs: self.objects.append({'pk': obj['pk'], 'obj': obj['obj']}) # Send post_add signal (instance should be Through instance but it's # the manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) if auto_save: self.model_instance.save()
def on_asset_delete(instance: Asset, using, **kwargs): node_ids = set(Node.objects.filter( assets=instance ).distinct().values_list('id', flat=True)) setattr(instance, RELATED_NODE_IDS, node_ids) m2m_changed.send( sender=Asset.nodes.through, instance=instance, reverse=False, model=Node, pk_set=node_ids, using=using, action=PRE_REMOVE )
def add(self, *objs, **kwargs): """ Add model instance(s) to the M2M field. The objects can be real Model instances or just ObjectIds (or strings representing ObjectIds). Only supported kwarg is 'auto_save' :param auto_save: Defaults to True. When a model is added to the M2M, the behavior of Django is to create an entry in the through-table, which essentially saves the list. In order to do the equivalent, we need to save the model. However, that behavior is not the same as Django either because Django doesn't save the whole model object, so that's why this is optional. Swings and Roundabouts. """ auto_save = kwargs.pop('auto_save', True) using = router.db_for_write(self.model_instance if self.model_instance else self.field.model) add_objs = [] for obj in objs: if isinstance(obj, (ObjectId, basestring)): # It's an ObjectId pk = ObjectId(obj) instance = None else: # It's a model object pk = ObjectId(obj.pk) instance = obj if not pk in (obj['pk'] for obj in self.objects): add_objs.append({'pk':pk, 'obj':instance}) # Calculate list of object ids that are being added add_obj_ids = [str(obj['pk']) for obj in add_objs] # Send pre_add signal (instance should be Through instance but it's the # manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) # Commit the add for obj in add_objs: self.objects.append({'pk':obj['pk'], 'obj':obj['obj']}) # Send post_add signal (instance should be Through instance but it's # the manager instance for now) m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_add', reverse=False, model=self.rel.to, pk_set=add_obj_ids, using=using) if auto_save: self.model_instance.save()
def add_participant(self, user, role=None, **kwargs): update_fields = [] if role is not None: # if an invalid role is passed in then except if role not in self.permissions_model.ROLES.get_values(): raise Exception('Role is not a valid value must be in: %s see WorkspaceParticipants.ROLES' % (self.permissions_model.ROLES.get_values())) # Get the object perm, is_new = self.permissions_model.objects.get_or_create(user=user, workspace=self) if role is not None: perm.role = role update_fields.append('role') # # if role is None it will default to the WorkspaceParticipants.role default (currently .client) # if is_new: # only do this if new perm.is_matter_owner = False update_fields.append('is_matter_owner') if user == self.lawyer: perm.is_matter_owner = True perm.role = self.permissions_model.ROLES.owner update_fields.append('role') # Allow override of permissions if kwargs: permissions = self.permissions_model.clean_permissions(**kwargs) else: # no specific permissions were passed in # so get the roles default permissions permissions = perm.default_permissions() perm.permissions = permissions update_fields.append('data') if update_fields: perm.save(update_fields=update_fields) m2m_changed.send(sender=self.__class__.participants.through, instance=self, action='post_add', model=perm.__class__, pk_set=[perm.pk]) return perm
def send_m2m_changed_signal(self, instances, action): if not isinstance(instances, list): instances = [instances] from_to_mapper = defaultdict(list) for i in instances: to_id = getattr(i, self.to_field).id from_obj = getattr(i, self.from_field) from_to_mapper[from_obj].append(to_id) for from_obj, to_ids in from_to_mapper.items(): m2m_changed.send( sender=self.through, instance=from_obj, action=action, reverse=False, model=self.to_model, pk_set=to_ids )
def remove(self, *objs, **kwargs): """ Remove the specified object from the M2M field. The object can be a real model instance or an ObjectId or a string representing an ObjectId. The related object is not deleted, it's only removed from the list. Only supported kwarg is 'auto_save' :param auto_save: See add() above for description """ auto_save = kwargs.pop('auto_save', True) obj_ids = set([ ObjectId(obj) if isinstance(obj, (ObjectId, basestring)) else ObjectId(obj.pk) for obj in objs ]) # Calculate list of object ids that will be removed removed_obj_ids = [ str(obj['pk']) for obj in self.objects if obj['pk'] in obj_ids ] # Send the pre_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) # Commit the remove self.objects = [ obj for obj in self.objects if obj['pk'] not in obj_ids ] # Send the post_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) if auto_save: self.model_instance.save()
def clear(self): """ Clear all objecst in the list. The related objects are not deleted from the database. """ # Calculate list of object ids that will be removed removed_obj_ids = [str(obj['pk']) for obj in self.objects] # Send the pre_clear signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_clear', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) # Commit the clear self.objects = [] # Send the post_clear signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_clear', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) return self
def send_post_add_signal(self, instance): if not isinstance(instance, list): instance = [instance] system_users_objects_map = defaultdict(list) model, object_field = self.get_objects_attr() for i in instance: _id = getattr(i, object_field).id system_users_objects_map[i.systemuser].append(_id) sender = self.get_sender() for system_user, object_ids in system_users_objects_map.items(): logger.debug('System user relation changed, send m2m_changed signals') m2m_changed.send( sender=sender, instance=system_user, action='post_add', reverse=False, model=model, pk_set=set(object_ids) )
def send(self, message, recivers, email=False): pk_set = [] for reciver in recivers: pk_set.append(reciver.pk) MessageState.objects.get_or_create( message=message, user=reciver ) # メールが届いていることをCallする site.get_backend(Message).autodiscover(message, created=True, user_to=reciver) # Many to Manyを手動変更したのでシグナルを送信する m2m_changed.send( sender=Message.recivers.through, instance=message, action='post_add', reverse=False, model=User, pk_set=pk_set) return message
def remove(self, *objs): """ Remove the specified object from the M2M field. The object can be a real model instance or an ObjectId or a string representing an ObjectId. The related object is not deleted, it's only removed from the list. """ obj_ids = set([ObjectId(obj) if isinstance(obj, (ObjectId, basestring)) else ObjectId(obj.pk) for obj in objs]) # Calculate list of object ids that will be removed removed_obj_ids = [str(obj['pk']) for obj in self.objects if obj['pk'] in obj_ids] # Send the pre_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='pre_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) # Commit the remove self.objects = [obj for obj in self.objects if obj['pk'] not in obj_ids] # Send the post_remove signal m2m_changed.send(self.rel.through, instance=self.model_instance, action='post_remove', reverse=False, model=self.rel.to, pk_set=removed_obj_ids) return self
def redirect_m2m_changed_permissions(sender, signal=None, *args, **kwargs): m2m_changed.send(BaseGroup, *args, **kwargs)
def redirect_m2m_changed_permissions(sender, signal=None, *args, **kwargs): m2m_changed.send(BaseUser, *args, **kwargs)
def redirect_m2m_changed_groups(sender, signal=None, *args, **kwargs): m2m_changed.send(BaseUser, *args, **kwargs)