I think this works now!!!

This commit is contained in:
John Mullins
2023-08-25 14:14:34 +10:00
parent 4008b7e19f
commit 45149ffb5d
+62 -64
View File
@@ -1,14 +1,12 @@
from functools import update_wrapper
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.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):
@@ -18,6 +16,7 @@ class CloneModelAdmin(ModelAdmin):
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 wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
@@ -30,15 +29,16 @@ class CloneModelAdmin(ModelAdmin):
new_urlpatterns = [
path(
"<path:object_id>/clone/",
wrap(self.clone_view),
wrap(self.cloneform_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
# 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):
print(object_id)
@@ -52,89 +52,87 @@ class CloneModelAdmin(ModelAdmin):
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):
def cloneform_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
return self._get_obj_does_not_exist_redirect(
request, self.opts, object_id
)
model_form = self.get_form(request)
new_obj = self.model()
formsets = []
fieldsets = self.get_fieldsets(request, None)
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 form.is_valid():
new_obj = self.save_form(request, form, change=False)
if request.method == "POST":
form = model_form(request.POST)
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 = {}
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)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, False)
self.save_related(request, form, formsets, False)
change_message = self.construct_change_message(
request, form, formsets, False
)
self.log_addition(request, new_object, change_message)
return self.response_add(request, new_object)
else:
form_validated = False
else:
new_obj = self.model()
for field in self.cloneable_fields:
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(
form,
list(self.get_fieldsets(request)),
self.get_prepopulated_fields(request),
self.get_readonly_fields(request),
self.readonly_fields,
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)
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"
**self.admin_site.each_context(request),
"title": title,
"original": title,
"adminform": admin_form,
"is_popup": "_popup" in request.POST or "_popup" in request.GET,
"show_delete": False,
"media": media,
"inline_admin_formsets": inline_formsets,
"errors": helpers.AdminErrorList(form, formsets),
**(extra_context or {}),
}
context.update(extra_context or {})
return self.render_change_form(
@@ -142,5 +140,5 @@ class CloneModelAdmin(ModelAdmin):
context,
form_url=form_url,
change=False,
add=False
)
add=True
)