Index: django/newforms/models.py =================================================================== --- django/newforms/models.py (revision 7028) +++ django/newforms/models.py (working copy) @@ -53,6 +53,9 @@ continue if f.name in cleaned_data: f.save_form_data(instance, cleaned_data[f.name]) + postm2m = getattr(form,'post_m2m',None) + if postm2m: + postm2m(instance) if commit: # If we are committing, save the instance and the m2m data immediately. instance.save() @@ -76,7 +79,7 @@ return save def form_for_model(model, form=BaseForm, fields=None, - formfield_callback=lambda f: f.formfield()): + formfield_callback=lambda f: f.formfield(), post_m2m_callback=None): """ Returns a Form class for the given Django model class. @@ -101,10 +104,11 @@ base_fields = SortedDict(field_list) return type(opts.object_name + 'Form', (form,), {'base_fields': base_fields, '_model': model, - 'save': make_model_save(model, fields, 'created')}) + 'save': make_model_save(model, fields, 'created'), + 'post_m2m':post_m2m_callback}) def form_for_instance(instance, form=BaseForm, fields=None, - formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)): + formfield_callback=lambda f, **kwargs: f.formfield(**kwargs), post_m2m_callback=None): """ Returns a Form class for the given Django model instance. @@ -132,7 +136,8 @@ base_fields = SortedDict(field_list) return type(opts.object_name + 'InstanceForm', (form,), {'base_fields': base_fields, '_model': model, - 'save': make_instance_save(instance, fields, 'changed')}) + 'save': make_instance_save(instance, fields, 'changed'), + 'post_m2m':post_m2m_callback}) def form_for_fields(field_list): """ @@ -457,7 +462,11 @@ """Saves model instances for every form, adding and changing instances as necessary, and returns the list of instances. """ - return self.save_existing_objects(commit) + self.save_new_objects(commit) + res = self.save_existing_objects(commit) + self.save_new_objects(commit) + post_formset = getattr(self,'post_formset',None) + if post_formset: + self.post_formset(res) + return res def save_existing_objects(self, commit=True): if not self.queryset: @@ -495,7 +504,8 @@ super(BaseModelFormSet, self).add_fields(form, index) def formset_for_model(model, form=BaseForm, formfield_callback=lambda f: f.formfield(), - formset=BaseModelFormSet, extra=1, orderable=False, deletable=False, fields=None): + formset=BaseModelFormSet, extra=1, orderable=False, deletable=False, fields=None, + post_m2m_callback=None, post_formset_callback=None): """ Returns a FormSet class for the given Django model class. This FormSet will contain change forms for every instance of the given model as well @@ -504,8 +514,10 @@ This is essentially the same as ``formset_for_queryset``, but automatically uses the model's default manager to determine the queryset. """ - form = form_for_model(model, form=form, fields=fields, formfield_callback=formfield_callback) + form = form_for_model(model, form=form, fields=fields, formfield_callback=formfield_callback, + post_m2m_callback=post_m2m_callback) FormSet = formset_for_form(form, formset, extra, orderable, deletable) + FormSet.post_formset = post_formset_callback FormSet.model = model return FormSet @@ -559,7 +571,8 @@ raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model)) return fk -def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, formfield_callback=lambda f: f.formfield()): +def inline_formset(parent_model, model, fk_name=None, fields=None, extra=3, orderable=False, deletable=True, + formfield_callback=lambda f: f.formfield(), post_m2m_callback=None,post_formset_callback=None): """ Returns an ``InlineFormset`` for the given kwargs. @@ -571,7 +584,8 @@ FormSet = formset_for_model(model, formset=InlineFormset, fields=fields, formfield_callback=formfield_callback, extra=extra, orderable=orderable, - deletable=deletable) + deletable=deletable,post_m2m_callback=post_m2m_callback, + post_formset_callback=post_formset_callback) # HACK: remove the ForeignKey to the parent from every form # This should be done a line above before we pass 'fields' to formset_for_model # an 'omit' argument would be very handy here Index: django/contrib/admin/options.py =================================================================== --- django/contrib/admin/options.py (revision 7028) +++ django/contrib/admin/options.py (working copy) @@ -342,7 +342,7 @@ fields = flatten_fieldsets(self.declared_fieldsets) else: fields = None - return forms.form_for_model(self.model, fields=fields, formfield_callback=self.formfield_for_dbfield) + return forms.form_for_model(self.model, fields=fields, formfield_callback=self.formfield_for_dbfield, post_m2m_callback=getattr(self,'post_m2m',None)) def form_change(self, request, obj): """ @@ -352,7 +352,7 @@ fields = flatten_fieldsets(self.declared_fieldsets) else: fields = None - return forms.form_for_instance(obj, fields=fields, formfield_callback=self.formfield_for_dbfield) + return forms.form_for_instance(obj, fields=fields, formfield_callback=self.formfield_for_dbfield, post_m2m_callback=getattr(self,'post_m2m',None)) def save_add(self, request, model, form, formsets, post_url_continue): """ @@ -742,7 +742,7 @@ fields = flatten_fieldsets(self.declared_fieldsets) else: fields = None - return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) + return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra, post_m2m_callback=getattr(self,'post_m2m',None), post_formset_callback=getattr(self,'post_formset',None)) def formset_change(self, request, obj): """Returns an InlineFormSet class for use in admin change views.""" @@ -750,7 +750,7 @@ fields = flatten_fieldsets(self.declared_fieldsets) else: fields = None - return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) + return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra, post_m2m_callback=getattr(self,'post_m2m',None), post_formset_callback=getattr(self,'post_formset',None)) def fieldsets_add(self, request): if self.declared_fieldsets: