From 4008b7e19f7beb1a844baffda696dd66b29a99b5 Mon Sep 17 00:00:00 2001 From: John Mullins Date: Fri, 25 Aug 2023 10:32:45 +1000 Subject: [PATCH] Added adminClone view --- busManager/coord/adminClone.py | 146 +++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 busManager/coord/adminClone.py diff --git a/busManager/coord/adminClone.py b/busManager/coord/adminClone.py new file mode 100644 index 0000000..42df3ad --- /dev/null +++ b/busManager/coord/adminClone.py @@ -0,0 +1,146 @@ + +from functools import update_wrapper +from django.contrib.admin import ModelAdmin, helpers +from django.contrib.admin.utils import unquote +from django.utils.functional import lazy +from django.forms.models import model_to_dict +from django.forms.formsets import all_valid +from django.urls import reverse, path +from django.core.exceptions import PermissionDenied +from django.http import Http404, HttpResponse +from django.db.models.fields.files import FieldFile, FileField + + +class CloneModelAdmin(ModelAdmin): + clone_verbose_name = "Clone" + change_form_template = 'admin/admin_change_form.html' + cloneable_fields = [] + + def get_urls(self): + + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + + wrapper.model_admin = self + return update_wrapper(wrapper, view) + + info = self.opts.app_label, self.opts.model_name + + new_urlpatterns = [ + path( + "/clone/", + wrap(self.clone_view), + name="%s_%s_clone" % info, + ), + # path("clone/", self.clone_view, name="%s_%s_clone" % info), + ] + + print(new_urlpatterns) + original_urlpatterns = super(CloneModelAdmin, self).get_urls() + return original_urlpatterns + new_urlpatterns + + def change_view(self, request, object_id, form_url='', extra_context=None): + print(object_id) + url = "{0}coord/traveller/{1}/clone/".format(reverse("admin:index"), object_id) + url = "/admin/coord/traveller/3/clone/" + extra_context = extra_context or {} + extra_context.update({ + 'clone_verbose_name': self.clone_verbose_name, + 'clone_link': url, + }) + print(extra_context) + return super(CloneModelAdmin, self).change_view(request, object_id, form_url, extra_context) + + def clone_view(self, request, object_id, form_url='', extra_context=None): + if not self.has_add_permission(request): + raise PermissionDenied + + original_obj = self.get_object(request, object_id) + + if original_obj is None: + raise Http404 + + model_form = self.get_form(request) + new_obj = self.model() + formsets = [] + + if False and formsets: + + form = model_form(request.POST, request.FILES) + if form.is_valid(): + new_obj = self.save_form(request, form, change=False) + + prefixes = {} + for FormSet, inline in self.get_formsets_with_inlines(request): + prefix = FormSet.get_default_prefix() + prefixes[prefix] = prefixes.get(prefix, 0) + 1 + if prefixes[prefix] != 1 or not prefix: + prefix = "%s-%s" % (prefix, prefixes[prefix]) + + request_files = request.FILES + filter_params = {'%s__pk' % original_obj.__class__.__name__.lower(): original_obj.pk} + inlined_objs = inline.model.objects.filter(**filter_params) + for n, inlined_obj in enumerate(inlined_objs.all()): + for field in inlined_obj._meta.fields: + if isinstance(field, FileField) and field not in request_files: + value = field.value_from_object(inlined_obj) + file_field_name = '{}-{}-{}'.format(prefix, n, field.name) + request_files.setdefault(file_field_name, value) + + formset = FormSet(data=request.POST, files=request_files, + instance=new_obj, + save_as_new="_saveasnew" in request.POST, # ???? + prefix=prefix) + formsets.append(formset) + + if all_valid(formsets) and form.is_valid(): + self.save_model(request, new_obj, form, False) + self.save_related(request, form, formsets, False) + try: + self.log_addition(request, new_obj) + except TypeError: + # In Django 1.9 we need one more param + self.log_addition(request, new_obj, "Cloned object") + + return self.response_add(request, new_obj, None) + + else: + for field in self.cloneable_fields: + setattr(new_obj, field, getattr(original_obj, field)) + + form = model_form(model_to_dict(new_obj)) + + admin_form = helpers.AdminForm( + form, + list(self.get_fieldsets(request)), + self.get_prepopulated_fields(request), + self.get_readonly_fields(request), + model_admin=self + ) + + media = self.media + admin_form.media + + inline_admin_formsets = self.get_inline_formsets(request, [], []) + title = u'{0} {1}'.format(self.clone_verbose_name, original_obj) + + context = { + 'title': title, + 'original': title, + 'adminform': admin_form, + 'is_popup': "_popup" in getattr(request, 'REQUEST', request.GET), + 'show_delete': False, + 'media': media, + 'inline_admin_formsets': inline_admin_formsets, + # 'errors': helpers.AdminErrorList(form, self.get_formsets_with_inlines(request)), + 'app_label': "coord" + } + context.update(extra_context or {}) + + return self.render_change_form( + request, + context, + form_url=form_url, + change=False, + add=False + ) \ No newline at end of file