Search code examples
djangodjango-admininlines

Django admin - saving inlines overriding save_formset


I'm relatively new to django (1.8) and have read around this issue which all points to overriding the save_formset function as per this link

https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_formset

Had added to an old thread (Django admin - how to save inlines?) but wanted to raise as a separate thread to get better visibility and besides this already been answered.

The function below works where I'm trying to amend the form before saving it, i.e. updating the audit fields (created/modified) to the USER and lowercase the 'enum_value_en' attribute. All works when user enters just 1 entry but when adding more it updates ALL entries with the SAME value (i.e. 'enum_value_en' in the database.

 def save_formset(self, request, form, formset, change):
    instances = formset.save(commit=False) # gets instance from memory and add to it before saving it
    for obj in formset.deleted_objects:
        obj.delete()
    for instance in instances:
        for form in formset: # cleaned_data is only available on the form, so you have to iterate over formset
            instance.modified_by = request.user
            instance.created_by = request.user
            instance.lowercase_enum_value_en = form.cleaned_data['enum_value_en'].lower()
            instance.save()
    formset.save_m2m()
  • Ex.

    if entries are 'a' & 'b', the lowercase attributes are set to 'b' on both records.

PS. Would also be grateful if anyone could offer some comments around their suggestions so that I can understand each line of code.

Most appreciated.


Solution

  • The problem is that you are looping over the instances, and then looping over the formsets within that. Say there are 5 forms, that means you are saving each instance 5 times, once for each instance. Every instance will end up with the same value from the final formset.

    In this case, I don't think you need to access the form's cleaned_data. Just access the instance's enum_value_en attribute. This means that you don't need the inner loop that is causing your problem.

    for instance in instances:
        instance.lowercase_enum_value_en = instance.enum_value_en.lower()
        instance.modified_by = request.user
        instance.created_by = request.user
        instance.save()