Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ManyToMany field not saved when using Django admin

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?

like image 623
kb. Avatar asked Jun 01 '11 11:06

kb.


People also ask

How can add data to Manytomany field in Django?

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.

How do you make a field non mandatory in Django admin?

The simplest way is by using the field option blank=True (docs.djangoproject.com/en/dev/ref/models/fields/#blank).

How do you make a field non editable in Django admin?

editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form.

How do you remove save and add another Django admin?

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.


2 Answers

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)
like image 198
kb. Avatar answered Sep 26 '22 01:09

kb.


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)
like image 30
Tomba Avatar answered Sep 26 '22 01:09

Tomba