Login

Django admin inline ordering - javascript only implementation

Author:
ojhilt
Posted:
December 5, 2012
Language:
JavaScript
Version:
1.4
Tags:
admin sorting ordering inline tabular-inlines
Score:
0 (after 0 ratings)

Having spent ages trying out various admin inline ordering packages and examples I found on here and elsewhere I failed to find a single one that did what I was after in the way I wanted or that worked, so I wrote one!

The general idea for this version was to be done purely in javascript, no additional methods or parameters required on your models, it's designed to be stuck in a js file and included in your admin class Media js parameter:

class Media:
    js = ['js/admin/widget_ordering.js', ]

Your model should have an integer column for sorting on, the name of this column should go in the 'sort_column' parameter at line 3 and your model should also obviously specify this in it's Meta 'ordering' class:

class Meta:
    ordering = ('rank',)

That's it! This is a pretty basic implementation that adds simple up and down buttons next to the sort order field, if you want to adapt this to use drag and drop or something, please feel free!

 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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
var ordering = (function($){

    var sort_column = 'rank';
    
    $(document).ready(function(){
        initialiseRows();
    });
    
    function initialiseRows(){
        var last_so = 0;
    
        $('div.inline-related tbody tr.form-row').not('.empty-form').not('add-row').each(function(i){
            // Gather the required items from this row
            var sort_td = $(this).find('.field-' + sort_column);
            var sort_input = $(this).find('.field-' + sort_column + ' input');
            var this_sort = parseInt(sort_input.val());
    
            // Remove any current movement buttons if this is a reinitialisation
            $(sort_td).find('.moveButton').remove();
    
            // On the off chance any existing bad sort data exists replace it so you always start with a clean order
            if(this_sort != last_so+1){
                $(sort_input).val(last_so+1);
                this_sort = last_so+1;
            }
            // Increment the sort loop value
            last_so = this_sort;
    
            // Setup the up/down button html for this row
            var btnUpHtml = '<input type="button" class="moveButton" value="Up" onclick="ordering.move(' + i + ', 1)">';
            var btnDownHtml = '<input type="button" class="moveButton" value="Down" onclick="ordering.move(' + i + ', 0)">';
    
            // Apply the up button to all but the first row
            if(this_sort > 1)
                $(sort_td).append(btnUpHtml);
    
            // Apply the down button to all but the last row
            if(this_sort < $('div.inline-related tbody tr.form-row').not('.empty-form').not('add-row').length)
                $(sort_td).append(btnDownHtml);
    
        });
    
        // Set the default sort of the hidden add row so new items don't jump to the top on save
        $('div.inline-related tbody tr.empty-form').find('.field-' + sort_column + ' input').val(last_so+1);
    }

    function moveRow(i, dir){
        // Grab all rows then find the one we are after and the one to swap it with
        var rows = $('div.inline-related tbody tr.form-row').not('.empty-form').not('add-row');
        var this_row = rows[i];
        var this_sort = parseInt($(this_row).find('.field-' + sort_column + ' input.vIntegerField').val());
        if (dir)
            var swap_row = rows[i-1];
        else
            var swap_row = rows[i+1];
        var swap_sort = parseInt($(swap_row).find('.field-' + sort_column + ' input.vIntegerField').val());

        // Swap the position of the rows and their sort order values
        if (dir)
            $(this_row).after($(swap_row));
        else
            $(swap_row).after($(this_row));
        $(this_row).find('.field-' + sort_column + ' input.vIntegerField').val(swap_sort);
        $(swap_row).find('.field-' + sort_column + ' input.vIntegerField').val(this_sort);

        // Reset the style classes to keep things pretty
        $(this_row).toggleClass('row1 row2');
        $(swap_row).toggleClass('row1 row2');

        // Re-initialise the rows to ensure the right buttons are in the right places
        initialiseRows();
    }

    return {
        move: moveRow
    }

})(django.jQuery);

More like this

  1. Dynamic tabular inlines with optional drag-n-drop sorting by Aneon 6 years, 2 months ago
  2. Dynamically add inlines by MasonM 6 years ago
  3. jstree integration to django admin by pawnhearts 5 years, 5 months ago
  4. GeoDjango maps in admin TabularInlines by alanB 4 years, 8 months ago
  5. Collapsed stacked inlines by Aneon 6 years, 1 month ago

Comments

Please login first before commenting.