I'm experiencing a weird problem which I hope someone in here may be able to shed some light on.
I'm overriding the save() method of a model to add some values to a ManyToMany-field after running super(). My problem is that when I'm saving in Django admin the values seems to get added to the relationship but is then empty again.
If however I do it from manage.py shell
it works without problem.
I've put two print statements in there and they produce the exact same output regardless of if I'm running it via Django admin or via shell.
class Store(models.Model):
holidays = models.ManyToManyField(StoreHoliday, blank=True)
copy_holidays_from = models.ForeignKey('Store', blank=True, null=True)
def save(self):
print '==== BEFORE SAVE:', self.holidays.all()
super(Store, self).save()
self.copy_holidays()
print '==== AFTER SAVE:', self.holidays.all()
def copy_holidays(self):
if self.pk and self.copy_holidays_from:
self.holidays.clear()
for h in self.copy_holidays_from.holidays.all():
self.holidays.add( h )
This is the output of the print
statements:
==== BEFORE SAVE: []
==== AFTER SAVE: [<StoreHoliday: 10 Mar 2010, Chuck Norris birthday (Closed)>]
Does anyone have any suggestions on what might be causing this?
Edit: All manual changes to the m2m relationship in save() seems to be discarded by Django when saving through the admin interface. Is this related to how it processes the form?
The add() function allows us to add an object to this ManyToManyField. And this is how to add an object to a ManyToManyField in Django.
The simplest way is by using the field option blank=True (docs.djangoproject.com/en/dev/ref/models/fields/#blank).
editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form.
The simplest option is to set save_as=True on the ModelAdmin . This will replace the "Save and add another" button with a "Save as new" button.
So it turns out the above was not the correct way to implement it. The code belonged in StoreAdmin, by overriding model_save().
This is how I solved it:
class StoreAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if obj.copy_holidays_from:
form.cleaned_data['holidays'] = obj.copy_holidays_from.holidays.all()
super(StoreAdmin, self).save_model(request, obj, form, change)
In django 2,1,4 my solution was to use save_related()
def save_related(self, request, form, formsets, change):
super().save_related(request, form, formsets, change)
form.instance.permissions.add(request.user)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With