I have a straight forward admin.ModelAdmin class with an inlines, of which I am overriding the form and formsets with a forms.Model and BaseInlineFormset to add a custom field. I have a custom jQuery script that gets loaded in and whenever a machine is picked from the select2 drop-down it runs an AJAX query to the REST API and grabs the items based on a foreign key value and populates the CleaningEntryInline with information. However, upon saving it is only posting a single record to the database.
class CleaningEntryInline(admin.TabularInline):
model = CleaningEntry
form = CleaningEntryForm
formset = CleaningEntryFormSet
extra = 0
raw_id_fields = ['cleaning_item']
fieldsets = [
(None,{'fields':[('cleaning_item','cleaning_action', 'checked', 'na', 'notes')]})
]
template = 'admin/quality/cleaningentry/edit_inline/tabular_actions.html'
class CleaningLogAdmin(admin.ModelAdmin):
####Save model function override to make and save QC Lab user and make uneditable.
def save_model(self, request, obj, form, change):
obj.lab_user = request.user.username
obj.save()
list_display = ['machine_used','get_product_info','lot_num','start_time','lab_user']
list_filter = ['machine_used']
readonly_fields = ['lab_user', 'cleaning_users']
search_fields = ['machine_cleaned', 'lot_num', 'recipe_cleaned__recipe_name__item_code', 'lab_user']
autocomplete_fields = ['machine_used','recipe_cleaned']
fieldsets = [
('Cleaning Info',{'fields':[('machine_used', 'recipe_cleaned', 'lot_num')]}),
(None,{'fields':[('start_time')]}),
(None,{'fields':[('clean_time', 'lab_user')]})
]
inlines = [CleaningUserInline, CleaningEntryInline]
change_list_template = 'admin/quality/cleaninglog/change_list.html'
list_per_page = 25
form = CleaningEntryForm
class Media:
js = (
'admin/js/vendor/jquery/jquery.min.js',
'admin/js/jquery.init.js',
'admin/js/list_filter_collaspe.js',
'admin/js/equipaction_filter.js',
)
css = {'all':(
'admin/css/vendor/select2/select2.css',
)
}
I've tried things like overriding save_formset() but I'm not entirely sure this is a Django issue and wondering if it's not due to namespaces?
If I append the rows manually by using the "Add another" button after the ajax call and I click "Save and Continue" or "Save" and check POST the form is submitting all the inlines but it only saves the 1st record listed and all the records I manually added.
My equipaction_filter.js:
$(document).ready(function () {
////Row container to append to table...
row_container = $(
'<tr class="form-row dynamic-log_entry row1" id="log_entry-0">'+
'<td class="original"><input type="hidden" name="log_entry-0-id" id="id_log_entry-0-id">'+
'<input type="hidden" name="log_entry-0-log_entry" id="id_log_entry-0-log_entry"></td>'+
'<td class="field-cleaning_item"><input type="text" name="log_entry-0-cleaning_item" class="vForeignKeyRawIdAdminField" id="id_log_entry-0-cleaning_item">'+
'<a href="/admin/quality/equipmentaction/?_to_field=id" class="related-lookup" id="lookup_id_log_entry-0-cleaning_item" title="Lookup"></a></td>'+
'<td class="field-cleaning_action"><input type="text" name="log_entry-0-cleaning_action" disabled="" id="id_log_entry-0-cleaning_action" style="width: 200px;"></td>'+
'<td class="field-checked"><input type="checkbox" name="log_entry-0-checked" id="id_log_entry-0-checked"></td>'+
'<td class="field-na"><input type="checkbox" name="log_entry-0-na" id="id_log_entry-0-na"></td>'+
'<td class="field-notes"><input type="text" name="log_entry-0-notes" maxlength="512" id="id_log_entry-0-notes" class="vTextField"></td>'+
'<td class="delete"></td></tr>'
);
//// This binds an ".on(select)" event function to the select2 box for the machine_used that
//// preforms an AJAX call using the machine_fk reference id to get all the EquipmentActions
//// records for that machine using REST API.
$("select#id_machine_used").on("select2:select", function(event) {
machine_fk = event.params.data.id;
var origin = window.location.origin;
$.ajax({
url:origin+'/pyscales/v1/quality/?machine_fk='+machine_fk,
crossDomain:true,
dataType:'json',
contentType: 'application/json',
//Upon a successful GET request, data is returned in JSON form.
success: function(data) {
console.log(data);
$("#id_log_entry-TOTAL_FORMS").val(data.count);
$(data.results).each(function (i, item) {
// console.log(i, item);
new_row = $(row_container[0].outerHTML.replace(/log_entry-0/,'log_entry-'+i));
new_row[0].children[1].children[0].value = item.id;
new_row[0].children[2].children[0].value = item.machine_fk+' | '+item.action;
var new_table = $('table.cleaning-table');
new_table.find('tbody').prepend(new_row);
});
}
});
});
});
})(django.jQuery);
I'd appreciate some feedback or constructive criticism. I'm still new to jQuery and I'm having a difficult time trying to understand the ins and outs. If I need to post something else please let me know. Thanks in advance.
After reviewing the code again and looking into the POST data, per @dirkgroten request, I noticed that on POST the .replace() regular expression I was using wasn't properly mapping the indexes to the forms:
new_row = $(row_container[0].outerHTML.replace(/log_entry-0/,'log_entry-'+i));
Should have been:
new_row = $(row_container[0].outerHTML.replace(/log_entry-0/
gi,'log_entry-'+i));
When the page mapped the data instead of a record for each row within the inline like so:
log_entry-0-cleaning_item:1
log_entry-1-cleaning_item:2
log_entry-2-cleaning_item:3
It was mapping multiple values to the same inline object that jQuery was creating:
log_entry-0-cleaning_item:
[0]:1
[0]:2
[0]:3