Copy of the Django many-to-many field

I have a Django model with two many-to-many fields. When the model is saved from the admin interface, I need to check if the second field is empty and if it is empty, I need elements from the first field copied to the second. How can i do this?

UPDATE

Matthew's answer seems to work fine, but I can't get the instance to save after I copied the field. I tried instance.save () without any success.

+4
source share
4 answers

The signal used is not post_save , but rather m2m_changed , which is sent after the model is saved to the database.

 @models.signals.m2m_changed(sender=MyModel.second_m2m.through) def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs): # just before adding a possibly empty set in "second_m2m", check and populate. if action == 'pre_add' and not pk_set: instance.__was_empty = True pk_set.update(instance.first_m2m.values_list('pk', flat=True)) @models.signals.m2m_changed(sender=MyModel.first_m2m.through) def duplicate_this_on_other_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs): # Just in case the "first_m2m" signals are sent after the other # so the actual "population" of the "second_m2m" is wrong: if action == 'post_add' and not pk_set and getattr(instance, '__was_empty'): instance.second_m2m = list(pk_set) delattr(instance, '__was_empty') 

Edit: the following code is simpler and based on new knowledge on model definition

In your code, the signals "first_m2m" are sent before "second_m2m" (it really depends on the definition of your model). Therefore, we can work under the assumption that when signals "second_m2m" are received, "first_m2m" is already filled with current data.

This makes us happier, because now you only need to check m2m-pre-add:

 @models.signals.m2m_changed(sender=MyModel.second_m2m.through) def duplicate_other_on_this_if_empty(sender, instance, action, reverse, model, pk_set, **kwargs): # just before adding a possibly empty set in "second_m2m", check and populate. if action == 'pre_add' and not pk_set: pk_set.update(instance.first_m2m.values_list('pk', flat=True)) 
+3
source

You can use the signal after saving. It seems like this is the best way to handle your needs here: the bonus is that it will work outside of the admin.

 @models.signals.post_save(sender=MyModel) def duplicate_missing_field(sender, instance, **kwargs): if not instance.my_second_m2m.count(): instance.my_second_m2m.add(*instance.my_first_m2m.all()) # or *instance.my_first_m2m.values_list('pk', flat=True), I think 

My code may not be quite right: you want to read signals in django.

+3
source

You can override the clean method for additional verification, so if the second many2many is empty, you can set default values, for example:

 def clean(self): super(MyClassModel, self).clean() if not self.MySecondMany2Many: # fill data 

you must install this code in the models.py file inside your class. if the net does not work, because the model must be saved, you can also override the save function, this is the same procedure.

I am not testing it, and I don’t think you can check if many2many is so empty, but you should get an idea :)

0
source

You can see admin save override the definition, just override it and check if the linked field is empty, if so, save the object, and get the related data from the second M2M and set it to the first M2M and save it again ...

0
source

All Articles