Many-to-many field, save() method and the Django admin caveat

Oct 30, 2013 · Updated: Jul 12, 2021 · by Tim Kamanin

Surprise surprise!

When you save a model via admin forms it's not an atomic transaction. The main object gets saved first (to make sure it has a PK), then the M2M is cleared and the new values set to whatever came out of the form.

So if you are in the save() of the main object you are in a window of opportunity where the M2M hasn't been updated yet. In fact, if you try to do something to the M2M, the change will get wiped out by the clear(). More info can be found here:

So if you want to add many to many relationships on model save (for example, you want to add categories) in model save method like these:

def save(self, *args, **kwargs):
    category = Category.objects.get(pk=1)

It won't work if you save model via admin, so to fix that you need to override save_related method on model admin form:

class ModelAdmin(admin.ModelAdmin):
    def save_related(self, request, form, formsets, change):
        super(ModelAdmin, self).save_related(request, form, formsets, change)
        category = Category.objects.get(pk=1)

And voila!

Hey, if you've found this useful, please share the post to help other folks find it:

There's even more:

Subscribe for updates

  • via Twitter: @timonweb
  • old school RSS:
  • or evergreen email ↓ ↓ ↓