diff --git a/busManager/coord/adminClone.py b/busManager/coord/adminClone.py index 42df3ad..5df94a4 100644 --- a/busManager/coord/adminClone.py +++ b/busManager/coord/adminClone.py @@ -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( "/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 /'> 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 - ) \ No newline at end of file + add=True + )