![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
![[community profile]](https://www.dreamwidth.org/img/silk/identity/community.png)
Here's an example of making an admin page that lets people reorder the items through drag and drop. It's *fairly* genericized already--you can use the same template for multiple data types--and has the potential to be MORE generic by creating a generic view sort of thing, but I haven't done that yet.
All you need is a model that has a (Integer or PositiveInteger) field named 'order'.
The form will let you reorder the items by drag and drop and save them, and also lets you link to the usual form to add an item.
The view function example:
The template (you might have to change where your Javascript libraries are):
All you need is a model that has a (Integer or PositiveInteger) field named 'order'.
The form will let you reorder the items by drag and drop and save them, and also lets you link to the usual form to add an item.
The view function example:
@login_required def reorder_datatypes(request): t = loader.get_template('admin/reorder.html') # can change what fields you can edit within the drag and drop items, like name DataTypeFormSet = modelformset_factory(DataType, extra = 0, fields=('display_name', 'code_name', 'order')) if request.method == "POST": formset = DataTypeFormSet(request.POST) if formset.is_valid(): formset.save() # reset the order to what's been saved formset = DataTypeFormSet(queryset=DataType.objects.order_by('order')) else: formset = DataTypeFormSet(queryset=DataType.objects.order_by('order')) c = Context({ 'title': 'Data Type Order', 'formset': formset, # change this to the admin add link of the item you are reordering 'new_item_url': reverse('admin:MyApp_datatype_add'), }) return HttpResponse(t.render(c))
The template (you might have to change where your Javascript libraries are):
{% extends "admin/base_site.html" %} {% block extrahead %} <script type="text/javascript" src="/media/js/jquery.js"></script> <link type="text/css" href="/media/jquery-ui/css/smoothness/jquery-ui-1.8.4.custom.css" rel="stylesheet" /> <script type="text/javascript" src="/media/jquery-ui/js/jquery-ui-1.8.4.custom.min.js"></script> <style> ul.order_list { list-style: none outside none; } li.order_item { padding: 10px; border: 1px solid #CCCCCC; margin: 5px; border-left: 5px solid #999; list-style: none outside none; } .hidden { display: none; } .red { background-color: #F00; } </style> <script type="text/javascript"> $(document).ready(function(){ // hide order fields $('span.order').addClass('hidden'); // turns the list into a sortable one $('ul.order_list').sortable({ update: function(event, ui) { var item_order = $(this).sortable('toArray'); // redo all of the order numbers in multiples of 10 for( i = 0; i < item_order.length; i++ ) { var item = item_order[i]; var new_order = (i + 1) * 10; var selector = '#'+item+' span.order input'; $(selector).val(new_order); } }, }); }); </script> {% endblock %} {% block content %} <ul> <li><a href="{{ new_item_url }}">Add new item</a></li> </ul> <form method="post" action=""> {{ formset.management_form }} <ul class="order_list"> {% for form in formset.forms %} <li class="order_item" id="item-{{ forloop.counter }}"> {% for field in form.visible_fields %} {# include hidden fields #} {% if forloop.first %} {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %} {% endif %} {% if "order" in field.html_name %} <span class="order"> {% else %} <span class="description"> {% endif %} {{ field.errors }} {{ field.label_tag}} {{ field }} </span> {% endfor %} </li> {% endfor %} </ul> <p><input type="submit" value="Save" /></p> </form> {% endblock %}