82 lines
2.4 KiB
Python
82 lines
2.4 KiB
Python
|
# coding: utf-8
|
||
|
"""
|
||
|
Make items sortable by drag-drop in list view. Diffierent from
|
||
|
builtin plugin sortable, it touches model field indeed intead
|
||
|
of only for display.
|
||
|
"""
|
||
|
|
||
|
from __future__ import unicode_literals
|
||
|
|
||
|
from django.template.loader import render_to_string
|
||
|
from django.urls.base import reverse
|
||
|
from django.db import transaction
|
||
|
|
||
|
from xadmin.views import (
|
||
|
BaseAdminPlugin, ModelAdminView, ListAdminView
|
||
|
)
|
||
|
from xadmin.sites import site
|
||
|
from xadmin.views.base import csrf_protect_m
|
||
|
|
||
|
|
||
|
class SortableListPlugin(BaseAdminPlugin):
|
||
|
|
||
|
list_order_field = None
|
||
|
|
||
|
def init_request(self, *args, **kwargs):
|
||
|
return bool(self.list_order_field)
|
||
|
|
||
|
@property
|
||
|
def is_list_sortable(self):
|
||
|
return True
|
||
|
|
||
|
def result_row(self, __, obj):
|
||
|
row = __()
|
||
|
row.update({
|
||
|
"tagattrs": "order-key=order_{}".format(obj.pk)
|
||
|
})
|
||
|
return row
|
||
|
|
||
|
def result_item(self, item, obj, field_name, row):
|
||
|
if self.is_list_sortable and field_name == self.list_order_field:
|
||
|
item.btns.append('<a><i class="fa fa-arrows"></i></a>')
|
||
|
return item
|
||
|
|
||
|
def get_context(self, context):
|
||
|
context['save_order_url'] = self.get_model_url(self.admin_view.model, 'save_order')
|
||
|
return context
|
||
|
|
||
|
def block_top_toolbar(self, context, nodes):
|
||
|
save_node = render_to_string(
|
||
|
'xadmin/blocks/model_list.top_toolbar.saveorder.html', context_instance=context
|
||
|
)
|
||
|
nodes.append(save_node)
|
||
|
|
||
|
def get_media(self, media):
|
||
|
if self.is_list_sortable:
|
||
|
media = media + self.vendor('xadmin.plugin.sortablelist.js')
|
||
|
return media
|
||
|
|
||
|
|
||
|
class SaveOrderView(ModelAdminView):
|
||
|
|
||
|
@csrf_protect_m
|
||
|
@transaction.atomic
|
||
|
def post(self, request):
|
||
|
order_objs = request.POST.getlist("order[]")
|
||
|
for order_value, pk in enumerate(order_objs, start=1):
|
||
|
self.save_order(pk, order_value)
|
||
|
return self.render_response({})
|
||
|
|
||
|
def save_order(self, pk, order_value):
|
||
|
obj = self.model.objects.get(pk=pk)
|
||
|
order_field = self.list_order_field
|
||
|
is_order_changed = lambda x: getattr(x, order_field) != order_value
|
||
|
|
||
|
if is_order_changed(obj):
|
||
|
setattr(obj, order_field, order_value)
|
||
|
obj.save()
|
||
|
|
||
|
|
||
|
site.register_plugin(SortableListPlugin, ListAdminView)
|
||
|
site.register_modelview(r'^save-order/$', SaveOrderView, name='%s_%s_save_order')
|