Added adminClone view

This commit is contained in:
John Mullins
2023-08-25 10:32:45 +10:00
parent 4e15e98801
commit 4008b7e19f
+146
View File
@@ -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(
"<path:object_id>/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
)