Skip to content

Instantly share code, notes, and snippets.

@devsnd
Last active October 4, 2023 15:27
Show Gist options
  • Save devsnd/38b9d4ff573a0611a87f10ab3042db45 to your computer and use it in GitHub Desktop.
Save devsnd/38b9d4ff573a0611a87f10ab3042db45 to your computer and use it in GitHub Desktop.
Quick hack to implement drag and drop for ordered model django admin
class DragndropOrderedModelAdmin(OrderedModelAdmin):
def move_above_view(self, request, object_id, other_object_id):
obj = get_object_or_404(self.model, pk=unquote(object_id))
other_obj = get_object_or_404(self.model, pk=unquote(other_object_id))
obj.above(other_obj)
# go back 3 levels (to get from /pk/move-above/other-pk back to the changelist)
return HttpResponseRedirect('../../../')
def get_urls(self):
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)
return [
url(
r'^(.+)/move-above/(\d+)/$',
wrap(self.move_above_view),
name='{app}_{model}_order_above'.format(**self._get_model_info())
),
] + super().get_urls()
def make_draggable(self, obj):
model_info = self._get_model_info()
url = reverse(
"{admin_name}:{app}_{model}_order_above".format(admin_name=self.admin_site.name, **model_info),
args=[-1, 0] # placeholder pks, will be replaced in js
)
return '''
<div class="pk-holder" data-pk="%s"></div> <!-- render the pk into each row -->
<style>[draggable=true] { -khtml-user-drag: element; }</style> <!-- fix for dragging in safari -->
<script>
window.__draggedObjPk = null;
django.jQuery(function () {
const $ = django.jQuery;
if (!window.__listSortableSemaphore) { // make sure this part only runs once
window.__move_to_url = '%s'; // this is the url including the placeholder pks
$('#result_list > tbody > tr').each(function(idx, tr) {
const $tr = $(tr);
$tr.attr('draggable', 'true');
const pk = $tr.find('.pk-holder').attr('data-pk');
$tr.attr('data-pk', pk);
$tr.on('dragstart', function (event) {
event.originalEvent.dataTransfer.setData('text/plain', null); // make draggable work in firefox
window.__draggedObjPk = $(this).attr('data-pk');
});
$tr.on('dragover', false); // make it droppable
$tr.on('drop', function (event) {
event.preventDefault(); // prevent firefox from opening the dataTransfer data
const otherPk = $(this).attr('data-pk');
console.log(window.__draggedObjPk, 'dropped on', otherPk);
const url = window.__move_to_url
.replace('\/0\/', '/' + otherPk + '/')
.replace('\/-1\/', '/' + window.__draggedObjPk + '/');
console.log('redirecting', url);
window.location = url;
});
});
window.__listSortableSemaphore = true;
}
});
</script>
''' % (obj.pk, url)
make_draggable.allow_tags = True
make_draggable.short_description = ''
@lsmith77
Copy link

lsmith77 commented Oct 4, 2023

ok no worries. thx for posting this back then!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment