From 6d8de7eb70b7b46942c8e184c55b250be8a35c28 Mon Sep 17 00:00:00 2001 From: Cuong Nguyen Date: Fri, 24 Feb 2023 19:05:23 +0700 Subject: [PATCH] enhance object tools --- admin_extended/base.py | 2 +- admin_extended/decorators.py | 11 +- admin_extended/mixins.py | 122 ++++++------------ .../templates/admin/change_form.html | 2 +- .../admin/custom/change_form_action.html | 31 ----- .../admin/custom/change_form_submit_row.html | 30 +++++ 6 files changed, 80 insertions(+), 118 deletions(-) delete mode 100644 admin_extended/templates/admin/custom/change_form_action.html create mode 100644 admin_extended/templates/admin/custom/change_form_submit_row.html diff --git a/admin_extended/base.py b/admin_extended/base.py index 7dbb52b..78bb2ae 100644 --- a/admin_extended/base.py +++ b/admin_extended/base.py @@ -4,7 +4,7 @@ from django.contrib import admin from django.shortcuts import render from django.urls import path -from .mixins import UIUtilsMixin, ChangeFormActionAdminModelMixin, ObjectToolModelAdminMixin +from .mixins import UIUtilsMixin, ObjectToolModelAdminMixin from .settings import ADMIN_EXTENDED_SETTINGS diff --git a/admin_extended/decorators.py b/admin_extended/decorators.py index b0f0b18..83c76d3 100644 --- a/admin_extended/decorators.py +++ b/admin_extended/decorators.py @@ -1,11 +1,18 @@ -def object_tool(function=None, *, icon=None, name=None, description=None): +def object_tool(function=None, *, icon=None, name=None, description=None, http_method='get', post_param_title=None): + """ + :http_method get | post. if http method is post, button will be place in submit row + :post_param_title Only affect if http method is post. Use when you want sumit form with one param. + """ + def decorator(func): func.icon = icon func.name = name func.description = description + func.http_method = http_method + func.post_param_title = post_param_title return func - + if function is None: return decorator return decorator(function) diff --git a/admin_extended/mixins.py b/admin_extended/mixins.py index 3cf10d8..41211dd 100644 --- a/admin_extended/mixins.py +++ b/admin_extended/mixins.py @@ -22,63 +22,6 @@ def format_json(self, content, indent=4): return format_html('
{}
', content) -class ChangeFormAction: - action_name = None - param_name = None - param_title = None - btn_color = None - - def handle(self, request): - raise NotImplementedError - - -class ChangeFormActionAdminModelMixin: - change_form_action_classes = [] - change_form_object_tools = [] - - def get_urls(self): - urls = super().get_urls() - opts = self.model._meta - action_url_name = '{}_{}_action'.format(opts.app_label, opts.model_name) - custom_urls = [ - path('action/', self.admin_site.admin_view(self.change_from_action_view), name=action_url_name), - ] - return custom_urls + urls - - def get_change_form_actions(self, request, object_id): - return [x() for x in self.change_form_action_classes] - - def get_change_form_object_tools1(self, request, object_id): - return self.change_form_object_tools - - def change_from_action_view(self, request): - if request.method == 'POST': - action_name = request.POST.get('action_name') - object_id = request.POST.get('object_id') - - change_form_action_registry = {x.action_name: x for x in self.get_change_form_actions(request, object_id)} - action = change_form_action_registry.get(action_name) - action.handle(request) - opts = self.model._meta - info = self.admin_site.name, opts.app_label, opts.model_name - change_url_name = '{}:{}_{}_change'.format(*info) - return redirect(change_url_name, object_id) - - def _changeform_view(self, request, object_id, form_url, extra_context): - if object_id: - change_form_actions = self.get_change_form_actions(request, object_id) - opts = self.model._meta - action_url_name = '{}:{}_{}_action'.format(self.admin_site.name, opts.app_label, opts.model_name) - - extra_context = extra_context if extra_context else {} - extra_context['change_form_actions'] = change_form_actions - extra_context['change_form_action_url'] = reverse(action_url_name) - - change_form_object_tools = self.get_change_form_object_tools1(request, object_id) - extra_context['change_form_object_tools'] = change_form_object_tools - - return super()._changeform_view(request, object_id, form_url, extra_context) - class ObjectToolModelAdminMixin: change_form_object_tools = [] change_list_object_tools = [] @@ -89,15 +32,15 @@ def get_urls(self): base_url_name = "%s_%s" % (self.model._meta.app_label, self.model._meta.model_name) custom_urls = [ path( - '/object-tools/', + '/object-tools/', self.admin_site.admin_view(self.change_form_object_tool_view), - name=f'{base_url_name}_change_form_object_tool' - ), + name=f'{base_url_name}_change_form_object_tool', + ), path( - 'object-tools/', + 'object-tools/', self.admin_site.admin_view(self.change_list_object_tool_view), - name=f'{base_url_name}_change_list_object_tool' - ), + name=f'{base_url_name}_change_list_object_tool', + ), ] return custom_urls + urls @@ -108,32 +51,44 @@ def get_change_form_object_tools(self, request): object_tools.append(object_tool) return {object_tool.name: object_tool for object_tool in object_tools} - def change_form_object_tool_view(self, request, object_id, name): change_form_object_tools = self.get_change_form_object_tools(request) return change_form_object_tools[name](request, object_id) - def _get_render_change_form_object_tools(self, request, object_id): base_url_name = "%s_%s" % (self.model._meta.app_label, self.model._meta.model_name) change_form_object_tools = self.get_change_form_object_tools(request) - result = [] - for name, object_tool in change_form_object_tools.items(): - result.append({ - 'icon': object_tool.icon, - 'url': reverse(f'admin:{base_url_name}_change_form_object_tool', args=[object_id, name]), - 'description': object_tool.description, - }) - return result + object_tool_position = [] + submit_row_position = [] + for name, object_tool in change_form_object_tools.items(): + if object_tool.http_method == 'get': + render_info = { + 'icon': object_tool.icon, + 'url': reverse(f'admin:{base_url_name}_change_form_object_tool', args=[object_id, name]), + 'description': object_tool.description, + } + object_tool_position.append(render_info) + + else: + submit_row_position.append( + { + 'icon': object_tool.icon, + 'url': reverse(f'admin:{base_url_name}_change_form_object_tool', args=[object_id, name]), + 'description': object_tool.description, + 'post_param_title': object_tool.post_param_title, + } + ) + return object_tool_position, submit_row_position def changeform_view(self, request, object_id=None, form_url="", extra_context=None): if object_id: extra_context = extra_context if extra_context else {} - extra_context['change_form_object_tools'] = self._get_render_change_form_object_tools(request, object_id) + object_tools = self._get_render_change_form_object_tools(request, object_id) + extra_context['change_form_object_tools'] = object_tools[0] + extra_context['change_form_submit_row'] = object_tools[1] return super().changeform_view(request, object_id, form_url, extra_context) - def get_change_list_object_tools(self, request): object_tools = [] @@ -142,7 +97,6 @@ def get_change_list_object_tools(self, request): object_tools.append(object_tool) return {object_tool.name: object_tool for object_tool in object_tools} - def change_list_object_tool_view(self, request, name): change_list_object_tools = self.get_change_list_object_tools(request) return change_list_object_tools[name](request) @@ -152,15 +106,17 @@ def _get_render_change_list_object_tools(self, request): change_list_object_tools = self.get_change_list_object_tools(request) result = [] for name, object_tool in change_list_object_tools.items(): - result.append({ - 'icon': object_tool.icon, - 'url': reverse(f'admin:{base_url_name}_change_list_object_tool', args=[name]), - 'description': object_tool.description, - }) + result.append( + { + 'icon': object_tool.icon, + 'url': reverse(f'admin:{base_url_name}_change_list_object_tool', args=[name]), + 'description': object_tool.description, + } + ) return result - + def changelist_view(self, request, extra_context=None): extra_context = extra_context if extra_context else {} extra_context['change_list_object_tools'] = self._get_render_change_list_object_tools(request) - return super().changelist_view(request, extra_context) \ No newline at end of file + return super().changelist_view(request, extra_context) diff --git a/admin_extended/templates/admin/change_form.html b/admin_extended/templates/admin/change_form.html index b5757ef..4f01c25 100644 --- a/admin_extended/templates/admin/change_form.html +++ b/admin_extended/templates/admin/change_form.html @@ -34,7 +34,7 @@ {% block content %} {{ block.super }} - {% include "admin/custom/change_form_action.html" %} + {% include "admin/custom/change_form_submit_row.html" %} {% endblock %} diff --git a/admin_extended/templates/admin/custom/change_form_action.html b/admin_extended/templates/admin/custom/change_form_action.html deleted file mode 100644 index bf49f87..0000000 --- a/admin_extended/templates/admin/custom/change_form_action.html +++ /dev/null @@ -1,31 +0,0 @@ -{% if change_form_actions %} -
- {% for action in change_form_actions %} -
- {% csrf_token %} - - - -
- {% endfor %} -
- {% endif %} - - diff --git a/admin_extended/templates/admin/custom/change_form_submit_row.html b/admin_extended/templates/admin/custom/change_form_submit_row.html new file mode 100644 index 0000000..f4e13a4 --- /dev/null +++ b/admin_extended/templates/admin/custom/change_form_submit_row.html @@ -0,0 +1,30 @@ +{% if change_form_submit_row %} +
+ {% for action in change_form_submit_row %} +
+ {% csrf_token %} + +
+ {% endfor %} +
+ {% endif %} + +