- Author:
- MasonM
- Posted:
- June 24, 2009
- Language:
- JavaScript
- Version:
- Not specified
- Score:
- 7 (after 7 ratings)
These functions use JQuery to dynamically add new entries for stacked or tabular inlines on a change form. To enable it, change the parent model to include this Javascript as well as JQuery. Here's an example:
class MeetingAdmin(admin.ModelAdmin):
inlines = [MeetingDonationInline, MeetingExtraInline]
class Media:
js = ["/media/jquery-1.3.2.min.js",
"/media/dynamic_inlines.js"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /* Following functions based off code written by Arne Brodowski
http://www.arnebrodowski.de/blog/507-Add-and-remove-Django-Admin-Inlines-with-JavaScript.html
*/
function increment_form_ids(el, to, name) {
var from = to-1
$(':input', $(el)).each(function(i,e){
var old_name = $(e).attr('name')
var old_id = $(e).attr('id')
$(e).attr('name', old_name.replace(from, to))
$(e).attr('id', old_id.replace(from, to))
$(e).val('')
})
}
function add_inline_form(name) {
var first = $('#id_'+name+'-0-id').parents('.inline-related')
// check to see if this is a stacked or tabular inline
if (first.hasClass("tabular")) {
var field_table = first.parent().find('table > tbody')
var count = field_table.children().length
var copy = $('tr:last', field_table).clone(true)
copy.removeClass("row1 row2")
copy.addClass("row"+((count % 2) == 0 ? 1 : 2))
field_table.append(copy)
increment_form_ids($('tr:last', field_table), count, name)
}
else {
var last = $(first).parent().children('.last-related')
var copy = $(last).clone(true)
var count = $(first).parent().children('.inline-related').length
$(last).removeClass('last-related')
var header = $('h3', copy)
header.html(header.html().replace("#"+count, "#"+(count+1)))
$(last).after(copy)
increment_form_ids($(first).parents('.inline-group').children('.last-related'), count, name)
}
$('input#id_'+name+'-TOTAL_FORMS').val(count+1)
return false;
}
// Add all the "Add Another" links to the bottom of each inline group
$(function() {
var html_template = '<ul class="tools">'+
'<li>'+
'<a class="add" href="#" onclick="return add_inline_form(\'{{prefix}}\')">'+
'Add another</a>'+
'</li>'+
'</ul>'
$('.inline-group').each(function(i) {
//prefix is in the name of the input fields before the "-"
var prefix = $("input[type='hidden']", this).attr("name").split("-")[0]
$(this).append(html_template.replace("{{prefix}}", prefix))
})
})
|
More like this
- Django Collapsed Stacked Inlines by applecat 1 year, 9 months ago
- Django Collapsed Stacked Inlines by mkarajohn 3 years, 10 months ago
- Dynamically adding forms to a formset. OOP version. by halfnibble 9 years, 6 months ago
- Convert multiple select for m2m to multiple checkboxes in django admin form by abidibo 11 years, 7 months ago
- Django admin inline ordering - javascript only implementation by ojhilt 11 years, 11 months ago
Comments
An improvement would be to add the "add a new inline" button using JavaScript . This would give you two advantages: first, there's no need to alter the template itself (you can just use Media.js to add the script). Secondly, it means that users without JavaScript won't see a link that doesn't do anything.
#
I did something similar. The bit I disagree with here is the 'copy the appropriate file ... into your project's template directory' bit. That makes upgrading Django a headache.
Instead I simply created the 'Add' link dynamically: $('.inline-group').append('<div class="add-item">Add another</div>');
(Jquery used in that example)
#
Good idea. The reason I didn't do this was because I had already extended the stacked and tabular inline templates in my project for other purposes. I doubt many others are in that situation, so I went ahead and added that feature.
#
If there is an inline with max_num=1, the javascript function should not be there, {% ifnotequal inline_admin_formset.formset.max_num 1 %} in your template code prevents this from happening.
#
Just a tip, it's best practice to always use semicolons in javascript. The fact that they aren't enforced is definitely a bug and not a feature of the language. (One example of why: if this script was minified it wouldn't work because minification removes newlines)
Regardless, very handy script. Cheers.
#
i noticed that js for prepopulated fields (like slugs) doesn't work with the newly created inlines, since the necessary script (from django/contrib/admin/templates/admin/prepopulated_fields_js.html) isn't also created. i don't know what the solution to this is, since in some cases (extra=0 for inlines with slugfields) there wouldn't even be script to duplicate.
#
Please login first before commenting.