I think this works now!!!

This commit is contained in:
John Mullins
2023-08-25 14:14:34 +10:00
parent 4008b7e19f
commit 45149ffb5d
+61 -63
View File
@@ -1,14 +1,12 @@
from functools import update_wrapper from functools import update_wrapper
from django.contrib.admin import ModelAdmin, helpers from django.contrib.admin import ModelAdmin, helpers
from django.contrib.admin.utils import unquote from django.contrib.admin.utils import unquote, flatten_fieldsets
from django.utils.functional import lazy from django.utils.functional import lazy
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from django.forms.formsets import all_valid from django.forms.formsets import all_valid
from django.urls import reverse, path from django.urls import reverse, path
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponse
from django.db.models.fields.files import FieldFile, FileField
class CloneModelAdmin(ModelAdmin): class CloneModelAdmin(ModelAdmin):
@@ -18,6 +16,7 @@ class CloneModelAdmin(ModelAdmin):
def get_urls(self): def get_urls(self):
# Not certain what this wrap() function is exactly. Just copied it from the django admin get_urls function
def wrap(view): def wrap(view):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs) return self.admin_site.admin_view(view)(*args, **kwargs)
@@ -30,15 +29,16 @@ class CloneModelAdmin(ModelAdmin):
new_urlpatterns = [ new_urlpatterns = [
path( path(
"<path:object_id>/clone/", "<path:object_id>/clone/",
wrap(self.clone_view), wrap(self.cloneform_view),
name="%s_%s_clone" % info, 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() original_urlpatterns = super(CloneModelAdmin, self).get_urls()
return original_urlpatterns + new_urlpatterns
# Important to add custom urls before the existing ones.
# Last entry is <URLPattern '<path:object_id>/'> which will pick up everything not already picked up
return new_urlpatterns + original_urlpatterns
def change_view(self, request, object_id, form_url='', extra_context=None): def change_view(self, request, object_id, form_url='', extra_context=None):
print(object_id) print(object_id)
@@ -52,89 +52,87 @@ class CloneModelAdmin(ModelAdmin):
print(extra_context) print(extra_context)
return super(CloneModelAdmin, self).change_view(request, object_id, form_url, 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): def cloneform_view(self, request, object_id, form_url='', extra_context=None):
if not self.has_add_permission(request): if not self.has_add_permission(request):
raise PermissionDenied raise PermissionDenied
original_obj = self.get_object(request, object_id) original_obj = self.get_object(request, object_id)
if original_obj is None: if original_obj is None:
raise Http404 return self._get_obj_does_not_exist_redirect(
request, self.opts, object_id
)
model_form = self.get_form(request) fieldsets = self.get_fieldsets(request, None)
new_obj = self.model()
formsets = []
if False and formsets: model_form = self.get_form(
request, None, change=False, fields=flatten_fieldsets(fieldsets)
)
form = model_form(request.POST, request.FILES) if request.method == "POST":
if form.is_valid(): form = model_form(request.POST)
new_obj = self.save_form(request, form, change=False) formsets, inline_instances = self._create_formsets(
request,
form.instance,
change=False,
)
form_validated = form.is_valid()
if form_validated:
new_object = self.save_form(request, form, change=False)
else:
new_object = form.instance
prefixes = {} if all_valid(formsets) and form_validated:
for FormSet, inline in self.get_formsets_with_inlines(request): self.save_model(request, new_object, form, False)
prefix = FormSet.get_default_prefix() self.save_related(request, form, formsets, False)
prefixes[prefix] = prefixes.get(prefix, 0) + 1 change_message = self.construct_change_message(
if prefixes[prefix] != 1 or not prefix: request, form, formsets, False
prefix = "%s-%s" % (prefix, prefixes[prefix]) )
self.log_addition(request, new_object, change_message)
request_files = request.FILES return self.response_add(request, new_object)
filter_params = {'%s__pk' % original_obj.__class__.__name__.lower(): original_obj.pk} else:
inlined_objs = inline.model.objects.filter(**filter_params) form_validated = False
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: else:
new_obj = self.model()
for field in self.cloneable_fields: for field in self.cloneable_fields:
setattr(new_obj, field, getattr(original_obj, field)) setattr(new_obj, field, getattr(original_obj, field))
form = model_form(instance=new_obj)
form = model_form(model_to_dict(new_obj)) formsets, inline_instances = self._create_formsets(
request, new_obj, change=True
)
admin_form = helpers.AdminForm( admin_form = helpers.AdminForm(
form, form,
list(self.get_fieldsets(request)), list(self.get_fieldsets(request)),
self.get_prepopulated_fields(request), self.get_prepopulated_fields(request),
self.get_readonly_fields(request), self.readonly_fields,
model_admin=self model_admin=self
) )
media = self.media
media = self.media + admin_form.media inline_formsets = self.get_inline_formsets(
request, formsets, inline_instances
)
for inline_formset in inline_formsets:
media += inline_formset.media
inline_admin_formsets = self.get_inline_formsets(request, [], [])
title = u'{0} {1}'.format(self.clone_verbose_name, original_obj) title = u'{0} {1}'.format(self.clone_verbose_name, original_obj)
context = { context = {
'title': title, **self.admin_site.each_context(request),
'original': title, "title": title,
'adminform': admin_form, "original": title,
'is_popup': "_popup" in getattr(request, 'REQUEST', request.GET), "adminform": admin_form,
'show_delete': False, "is_popup": "_popup" in request.POST or "_popup" in request.GET,
'media': media, "show_delete": False,
'inline_admin_formsets': inline_admin_formsets, "media": media,
# 'errors': helpers.AdminErrorList(form, self.get_formsets_with_inlines(request)), "inline_admin_formsets": inline_formsets,
'app_label': "coord" "errors": helpers.AdminErrorList(form, formsets),
**(extra_context or {}),
} }
context.update(extra_context or {}) context.update(extra_context or {})
return self.render_change_form( return self.render_change_form(
@@ -142,5 +140,5 @@ class CloneModelAdmin(ModelAdmin):
context, context,
form_url=form_url, form_url=form_url,
change=False, change=False,
add=False add=True
) )