Last active
October 4, 2023 15:27
-
-
Save devsnd/38b9d4ff573a0611a87f10ab3042db45 to your computer and use it in GitHub Desktop.
Quick hack to implement drag and drop for ordered model django admin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = '' |
You may also need to wrap the return value of make_draggable with mark_safe if you run into trouble!
did you manage to get this working with current versions?
Oof, I posted this 4 years ago, I can't even remember having written this! Sorry, I have no idea what changes would be need for current versions!
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
Imports required to make this work: