def get_mass_upload_context(self, request): model = self.model opts = model._meta self.register_newman_variables(request) # To enable admin-specific fields, we need to run the form class # through modelform_factory using curry FormClass = modelform_factory( Photo, form=MassUploadForm, fields=flatten_fieldsets(self.mass_upload_fieldsets), formfield_callback=curry(self.formfield_for_dbfield, request=request)) context = {} if request.method == 'POST': error_dict = {} # Unfortunately, FLASH uploader sends array data in weird format # so that Django doesn't recognize it as array of values, but # as one string with commas inside. The only way to expect it # and preprocess the values by ourselves. data = dict((key, val) for key, val in request.POST.items()) form = FormClass(data, request.FILES) if form.is_valid(): # To prevent newman from handling our field by common flash editor # we need to use a different mechanism new_object = form.save(commit=False) new_object.image = form.cleaned_data['image_file'] new_object.save() form.save_m2m() context.update({'object': new_object}) else: for e in form.errors: error_dict[u"id_%s" % e] = [u"%s" % ee for ee in form.errors[e]] context.update({'error_dict': error_dict}) else: form = FormClass() adminForm = helpers.AdminForm(form, list(self.mass_upload_fieldsets), self.prepopulated_fields) media = self.media + adminForm.media context.update({ 'title': _('Mass upload'), 'adminform': adminForm, 'is_popup': request.REQUEST.has_key('_popup'), 'show_delete': False, 'media': media, 'inline_admin_formsets': [], 'errors': helpers.AdminErrorList(form, ()), 'root_path': self.admin_site.root_path, 'app_label': opts.app_label, 'opts': opts, 'has_change_permission': self.has_change_permission(request, None), 'raw_form': form }) return context
def merge(modeladmin, request, queryset): # noqa """ Merge two model instances. Move all foreign keys. """ opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label, get_permission_codename('adminactions_merge', opts)) if not request.user.has_perm(perm): messages.error( request, _('Sorry you do not have rights to execute this action')) return def raw_widget(field, **kwargs): """ force all fields as not required""" kwargs['widget'] = TextInput({'class': 'raw-value'}) return field.formfield(**kwargs) merge_form = getattr(modeladmin, 'merge_form', MergeForm) MForm = modelform_factory(modeladmin.model, form=merge_form, exclude=('pk', ), formfield_callback=raw_widget) OForm = modelform_factory(modeladmin.model, exclude=('pk', ), formfield_callback=raw_widget) tpl = 'adminactions/merge.html' # transaction_supported = model_supports_transactions(modeladmin.model) ctx = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'transaction_supported': 'Un', 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'fields': [ f for f in queryset.model._meta.fields if not f.primary_key and f.editable ], 'app_label': queryset.model._meta.app_label, 'result': '', 'opts': queryset.model._meta } if 'preview' in request.POST: master = queryset.get(pk=request.POST.get('master_pk')) original = clone_instance(master) other = queryset.get(pk=request.POST.get('other_pk')) formset = formset_factory(OForm)( initial=[model_to_dict(master), model_to_dict(other)]) with transaction.nocommit(): form = MForm(request.POST, instance=master) other.delete() form_is_valid = form.is_valid() if form_is_valid: ctx.update({'original': original}) tpl = 'adminactions/merge_preview.html' else: master = queryset.get(pk=request.POST.get('master_pk')) other = queryset.get(pk=request.POST.get('other_pk')) elif 'apply' in request.POST: master = queryset.get(pk=request.POST.get('master_pk')) other = queryset.get(pk=request.POST.get('other_pk')) formset = formset_factory(OForm)( initial=[model_to_dict(master), model_to_dict(other)]) with transaction.nocommit(): form = MForm(request.POST, instance=master) stored_pk = other.pk other.delete() ok = form.is_valid() other.pk = stored_pk if ok: if form.cleaned_data['dependencies'] == MergeForm.DEP_MOVE: related = api.ALL_FIELDS else: related = None fields = form.cleaned_data['field_names'] api.merge(master, other, fields=fields, commit=True, related=related) return HttpResponseRedirect(request.path) else: messages.error(request, form.errors) else: try: master, other = queryset.all() # django 1.4 need to remove the trailing milliseconds for field in master._meta.fields: if isinstance(field, models.DateTimeField): for target in (master, other): raw_value = getattr(target, field.name) if raw_value: fixed_value = datetime(raw_value.year, raw_value.month, raw_value.day, raw_value.hour, raw_value.minute, raw_value.second) setattr(target, field.name, fixed_value) except ValueError: messages.error(request, _('Please select exactly 2 records')) return initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': 0, 'generic': MergeForm.GEN_IGNORE, 'dependencies': MergeForm.DEP_MOVE, 'action': 'merge', 'master_pk': master.pk, 'other_pk': other.pk } formset = formset_factory(OForm)( initial=[model_to_dict(master), model_to_dict(other)]) form = MForm(initial=initial, instance=master) adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media ctx.update({ 'adminform': adminForm, 'formset': formset, 'media': mark_safe(media), 'action_short_description': merge.short_description, 'title': u"%s (%s)" % ( merge.short_description.capitalize(), smart_text(modeladmin.opts.verbose_name_plural), ), 'master': master, 'other': other }) if django.VERSION[:2] > (1, 7): ctx.update(modeladmin.admin_site.each_context(request)) else: ctx.update(modeladmin.admin_site.each_context()) if django.VERSION[:2] > (1, 8): return render(request, tpl, context=ctx) else: return render_to_response(tpl, RequestContext(request, ctx))
def positions_by_category_view(self, request, category_id, extra_context=None): model = self.model self.user = request.user try: category = Category.objects.get(id=category_id) except Category.DoesNotExist: # FIXME: redirect return HttpResponseRedirect(reverse('newman:index')) names = ['featured_secondary_1', 'featured_secondary_2', 'featured_secondary_3', 'poll', 'tipoftheday', 'special', 'recipeoftheday', 'featured_small_1', 'featured_small_2', 'featured_small_3', ] positions = model.objects.filter(category=category_id, name__in=names) count = positions.count() PositionForm = self.get_form(request) if request.method == 'POST': forms = [PositionForm(request.POST, prefix=str(positions[x].id), instance=positions[x]) for x in range(count)] if all([form.is_valid() for form in forms]): for form in forms: new_object = self.save_form(request, form, change=True) self.save_model(request, new_object, form, change=True) change_message = self.construct_change_message(request, form, None) self.log_change(request, new_object, change_message) msg = unicode(_('Positions were changed successfully.')) return JsonResponse(msg, data={'category_id': category_id}) else: forms = [PositionForm(prefix=str(positions[x].id), instance=positions[x]) for x in range(count)] adminForms = [helpers.AdminForm(forms[x], self.get_fieldsets(request, positions[x]), self.prepopulated_fields) for x in range(count)] errors = [] for form in forms: errors.extend(helpers.AdminErrorList(form, [])) media = self.media if len(adminForms) > 0: media += adminForms[0].media raw_media = self.prepare_media(media) context = { 'multiple_edit': True, 'add': False, 'title': _('Positions in %s') % category.title, 'category': category, 'adminforms': adminForms, 'errors': errors, 'media': raw_media, 'is_popup': request.REQUEST.has_key('_popup'), } context.update(extra_context or {}) # render change form opts = self.model._meta app_label = opts.app_label ordered_objects = opts.get_ordered_objects() context.update({ 'app_label': app_label, 'change': True, 'has_add_permission': False, 'has_change_permission': True, 'has_delete_permission': False, 'has_file_field': False, 'has_absolute_url': hasattr(self.model, 'get_absolute_url'), 'ordered_objects': ordered_objects, 'opts': opts, 'content_type_id': ContentType.objects.get_for_model(self.model).id, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'save_url': reverse('newman:positions-by-category', args=[category_id]), }) return render_to_response("newman/%s/multi_change_form.html" % app_label, context, context_instance=template.RequestContext(request))
def add_view(self, request, form_url='', extra_context=None): "The 'add' admin view for this model." model = self.model opts = model._meta if not self.has_add_permission(request): raise PermissionDenied ModelForm = self.get_form(request) formsets = [] inline_instances = self.get_inline_instances(request, None) if request.method == 'POST': form = ModelForm(request.POST, request.FILES) if form.is_valid(): new_object = self.save_form(request, form, change=False) form_validated = True else: form_validated = False new_object = self.model() 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]) formset = FormSet(data=request.POST, files=request.FILES, instance=new_object, save_as_new="_saveasnew" in request.POST, prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if inline.inlines: self.add_nested_inline_formsets(request, inline, formset) if self.all_valid_with_nesting(formsets) and form_validated: self.save_model(request, new_object, form, False) self.save_related(request, form, formsets, False) args = () # Provide `add_message` argument to ModelAdmin.log_addition for # Django 1.9 and up. if VERSION[:2] >= (1, 9): add_message = self.construct_change_message( request, form, formsets, add=True ) args = (request, new_object, add_message) else: args = (request, new_object) self.log_addition(*args) return self.response_add(request, new_object) else: # Prepare the dict of initial data from the request. # We have to special-case M2Ms as a list of comma-separated PKs. initial = dict(request.GET.items()) for k in initial: try: f = opts.get_field(k) except models.FieldDoesNotExist: continue if isinstance(f, models.ManyToManyField): initial[k] = initial[k].split(",") form = ModelForm(initial=initial) 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]) formset = FormSet(instance=self.model(), prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if hasattr(inline, 'inlines') and inline.inlines: self.add_nested_inline_formsets(request, inline, formset) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.get_prepopulated_fields(request), self.get_readonly_fields(request), model_admin=self) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request)) readonly = list(inline.get_readonly_fields(request)) prepopulated = dict(inline.get_prepopulated_fields(request)) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets, prepopulated, readonly, model_admin=self) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media if hasattr(inline, 'inlines') and inline.inlines: other_media = self.wrap_nested_inline_formsets(request, inline, formset) if other_media is not None: media += other_media context = { 'title': _('Add %s') % force_text(opts.verbose_name), 'adminform': adminForm, 'is_popup': "_popup" in request.GET, 'show_delete': False, 'media': media, 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'app_label': opts.app_label, } context.update(self.admin_site.each_context(request)) context.update(extra_context or {}) return self.render_change_form(request, context, form_url=form_url, add=True)
def get_add_view_context(self, request, form_url): model = self.model opts = model._meta if not self.has_add_permission(request): raise PermissionDenied ModelForm = self.get_form(request) formsets = [] context = {} if request.method == 'POST': error_dict = {} form = ModelForm(request.POST.copy(), request.FILES) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=False) else: for e in form.errors: error_dict[u"id_%s" % e] = [ u"%s" % ee for ee in form.errors[e] ] form_validated = False new_object = self.model() prefixes = {} for FormSet in self.get_formsets(request): prefix = FormSet.get_default_prefix() prefix_no = prefixes.get(prefix, 0) prefixes[prefix] = prefix_no + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(data=request.POST.copy(), files=request.FILES, instance=new_object, save_as_new=request.POST.has_key("_saveasnew"), prefix=prefix) if not formset.is_valid(): for e in formset.errors[prefix_no]: error_dict[u"id_%s-%d-%s" % (prefix, prefix_no, e)] = [u"%s" % ee for ee in formset.errors[prefix_no][e]] formsets.append(formset) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, change=False) form.save_m2m() for formset in formsets: self.save_formset(request, form, formset, change=False) self.log_addition(request, new_object) self.response_add(request, new_object) context.update({ 'object': new_object, 'object_added': True, }) else: context.update({ 'error_dict': error_dict, }) else: # Prepare the dict of initial data from the request. # We have to special-case M2Ms as a list of comma-separated PKs. initial = dict(request.GET.items()) for k in initial: try: f = opts.get_field(k) except FieldDoesNotExist: continue if isinstance(f, ManyToManyField): initial[k] = initial[k].split(",") form = ModelForm(initial=initial) prefixes = {} for FormSet in self.get_formsets(request): prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=self.model(), prefix=prefix) formsets.append(formset) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(self.inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request)) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets) inline_admin_formset = self.get_inline_admin_formset(inline, formset, fieldsets) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media context.update({ 'title': _('Add %s') % force_unicode(opts.verbose_name), 'adminform': adminForm, 'is_popup': request.REQUEST.has_key('_popup'), 'show_delete': False, 'media': media, 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'root_path': self.admin_site.root_path, 'app_label': opts.app_label, }) context['raw_form'] = form return context
def _changeform_view(self, request, object_id, form_url, extra_context): to_field = request.POST.get('_to_field', request.GET.get('_to_field')) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) # ----- NUMBER OF CANDIDATES number_candidates = 0 if all_valid(formsets): for formset in formsets: for f in formset: cd = f.cleaned_data candidate = cd.get('president_candidate') or cd.get('congress_candidate') delete = cd.get('DELETE') if candidate: number_candidates += 1 if delete: number_candidates -= 1 valid_number_candidates_congress = True if number_candidates > 350 or number_candidates <= 0: valid_number_candidates_congress = False # Message users if not valid_number_candidates_congress: msg = 'The number of candidates must be 350 or less as well as having at least one candidate. There are now {} candidates.'.format(number_candidates) self.message_user(request, msg, messages.WARNING) # ----- END NUMBER OF CANDIDATES # ----- GENDER BALANCE LOAD CHECK women_number = 0 men_number = 0 if all_valid(formsets): for formset in formsets: for f in formset: cd = f.cleaned_data genre = cd.get('gender') delete = cd.get('DELETE') if genre == 'H': men_number += 1 elif genre == 'M': women_number += 1 if delete: if genre == 'H': men_number -= 1 elif genre == 'M': women_number -= 1 valid_genre_balance = True if women_number+men_number == 0: women_balance = 0 men_balance = 0 else: women_balance = (women_number/(women_number+men_number)) men_balance = (men_number/(women_number+men_number)) if women_balance < 0.4 or men_balance < 0.4 : valid_genre_balance = False # Message users if not valid_genre_balance: msg = 'The number of women candidates and the number of men candidates must be at least a 40% of the total candidates. Women: {}%, Men:{}%'.format(women_balance*100, men_balance*100) self.message_user(request, msg, messages.WARNING) # ----- END GENDER BALANCE LOAD CHECK if all_valid(formsets) and form_validated and valid_number_candidates_congress and valid_genre_balance: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message(request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets(request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields(request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % opts.verbose_name, adminform=adminForm, object_id=object_id, original=obj, is_popup=('_popup' in request.POST or '_popup' in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), ) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def _changeform_view(self, request, object_id, form_url, extra_context): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if request.method == 'POST': if not self.has_change_permission(request, obj): raise PermissionDenied else: if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message(request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets(request, form.instance, change=False) else: # Changed # 因为ArticleAdminForm中有Article没有的字段,这些字段的值不会变填充 # field_init_value就是用于给这些字段填充值用的 form = ModelForm(instance=obj, initial=self.field_init_value) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets(self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def mass_update(modeladmin, request, queryset): # noqa """ mass update queryset """ def not_required(field, **kwargs): """ force all fields as not required""" kwargs['required'] = False return field.formfield(**kwargs) def _doit(): errors = {} updated = 0 for record in queryset: for field_name, value_or_func in list(form.cleaned_data.items()): if callable(value_or_func): old_value = getattr(record, field_name) setattr(record, field_name, value_or_func(old_value)) else: setattr(record, field_name, value_or_func) if clean: record.clean() record.save() updated += 1 if updated: messages.info(request, _("Updated %s records") % updated) if len(errors): messages.error(request, "%s records not updated due errors" % len(errors)) adminaction_end.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin, form=form, errors=errors, updated=updated) opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label, get_permission_codename('adminactions_massupdate', opts)) if not request.user.has_perm(perm): messages.error( request, _('Sorry you do not have rights to execute this action')) return try: adminaction_requested.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin) except ActionInterrupted as e: messages.error(request, str(e)) return # Allows to specified a custom mass update Form in the ModelAdmin mass_update_form = getattr(modeladmin, 'mass_update_form', MassUpdateForm) MForm = modelform_factory(modeladmin.model, form=mass_update_form, exclude=('pk', ), formfield_callback=not_required) grouped = defaultdict(lambda: []) selected_fields = [] initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': 'mass_update' } if 'apply' in request.POST: form = MForm(request.POST) if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return HttpResponseRedirect(request.get_full_path()) # need_transaction = form.cleaned_data.get('_unique_transaction', False) validate = form.cleaned_data.get('_validate', False) clean = form.cleaned_data.get('_clean', False) if validate: with compat.atomic(): _doit() else: values = {} for field_name, value in list(form.cleaned_data.items()): if isinstance(form.fields[field_name], ModelMultipleChoiceField): messages.error( request, "Unable no mass update ManyToManyField without 'validate'" ) return HttpResponseRedirect(request.get_full_path()) elif callable(value): messages.error( request, "Unable no mass update using operators without 'validate'" ) return HttpResponseRedirect(request.get_full_path()) elif field_name not in [ '_selected_action', '_validate', 'select_across', 'action', '_unique_transaction', '_clean' ]: values[field_name] = value queryset.update(**values) return HttpResponseRedirect(request.get_full_path()) else: initial.update({'action': 'mass_update', '_validate': 1}) # form = MForm(initial=initial) prefill_with = request.POST.get('prefill-with', None) prefill_instance = None try: # Gets the instance directly from the queryset for data security prefill_instance = queryset.get(pk=prefill_with) except ObjectDoesNotExist: pass form = MForm(initial=initial, instance=prefill_instance) for el in queryset.all()[:10]: for f in modeladmin.model._meta.fields: if f.name not in form._no_sample_for: if hasattr(f, 'flatchoices') and f.flatchoices: grouped[f.name] = list( dict(getattr(f, 'flatchoices')).values()) elif hasattr(f, 'choices') and f.choices: grouped[f.name] = list( dict(getattr(f, 'choices')).values()) elif isinstance(f, df.BooleanField): grouped[f.name] = [True, False] else: value = getattr(el, f.name) if value is not None and value not in grouped[f.name]: grouped[f.name].append(value) initial[f.name] = initial.get(f.name, value) adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.date ) else str(obj) tpl = 'adminactions/mass_update.html' ctx = { 'adminform': adminForm, 'form': form, 'action_short_description': mass_update.short_description, 'title': u"%s (%s)" % ( mass_update.short_description.capitalize(), smart_text(modeladmin.opts.verbose_name_plural), ), 'grouped': grouped, 'fieldvalues': json.dumps(grouped, default=dthandler), 'change': True, 'selected_fields': selected_fields, 'is_popup': False, 'save_as': False, 'has_delete_permission': False, 'has_add_permission': False, 'has_change_permission': True, 'opts': modeladmin.model._meta, 'app_label': modeladmin.model._meta.app_label, # 'action': 'mass_update', # 'select_across': request.POST.get('select_across')=='1', 'media': mark_safe(media), 'selection': queryset } if django.VERSION[:2] > (1, 7): ctx.update(modeladmin.admin_site.each_context(request)) else: ctx.update(modeladmin.admin_site.each_context()) if django.VERSION[:2] > (1, 8): return render(request, tpl, context=ctx) else: return render_to_response(tpl, RequestContext(request, ctx))
def cb_changeform_view(self, request, *args, **kwargs): """ Like a change view in the admin. """ view_class = kwargs.get('view_class') add = kwargs.get('add', True) obj = kwargs.get('original', None) object_id = kwargs.get('object_id', None) title = kwargs.get('title', None) if hasattr(view_class, 'form_class'): form = view_class.form_class() else: form = None formsets = [] opts = self.model._meta TO_FIELD_VAR = False IS_POPUP_VAR = False change = not True view_on_site_url = None form_url = '' app_label = opts.app_label if form is not None: adminForm = helpers.AdminForm(form, formsets, {}, None, model_admin=self) media = self.media + adminForm.media admin_error_list = helpers.AdminErrorList(form, formsets) else: adminForm = None media = self.media admin_error_list = None to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) inline_formsets = None # From ``changeform_view`` if title is None: title = (_('Bulk add %s') if add else _('Bulk change %s') ) % force_text(opts.verbose_name_plural) context = dict( self.admin_site.each_context(request), title=title, adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=admin_error_list, preserved_filters=self.get_preserved_filters(request), ) # From ``render_change_form`` context.update({ 'add': add, 'change': change, 'has_add_permission': self.has_add_permission(request), 'has_change_permission': self.has_change_permission(request, obj), 'has_delete_permission': self.has_delete_permission(request, obj), 'has_file_field': True, # FIXME - this should check if form or formsets have a FileField, 'has_absolute_url': view_on_site_url is not None, 'absolute_url': view_on_site_url, 'form_url': form_url, 'opts': opts, 'content_type_id': get_content_type_for_model(self.model).pk, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'to_field_var': TO_FIELD_VAR, 'is_popup_var': IS_POPUP_VAR, 'app_label': app_label, 'media': self.media, }) original_get_context_data = view_class.get_context_data def _monkey_patch_get_context_data(instance, *args, **kwargs): data = original_get_context_data(instance, *args, **kwargs) data.update(context) return data view_class.get_context_data = _monkey_patch_get_context_data return view_class.as_view()(request)
def post(self, request, *args, **kwargs): service = get_service_instance() config = service.config item_id = kwargs.get('item_id', request.POST.get('item_id')) item_admin = self.get_item_admin() ModelForm = item_admin.get_form(request) if item_id: item = get_object_or_404(Item, pk=item_id) form = ModelForm(request.POST, instance=item) else: form = ModelForm(request.POST) if form.is_valid(): name = request.POST.get('name') category_id = request.POST.get('category') brand = request.POST.get('brand') reference = request.POST.get('reference') has_background_image = request.POST.get('has_background_image') if request.POST.get('has_background_image') else False original_id = request.POST.get('original_id') wholesale_price = request.POST.get('wholesale_price') try: retail_price = request.POST.get('retail_price') except: retail_price = 0 max_price = request.POST.get('max_price') summary = request.POST.get('summary') description = request.POST.get('description') badge_text = request.POST.get('badge_text') size = request.POST.get('size') weight = request.POST.get('weight') stock = request.POST.get('stock') unit_of_measurement = request.POST.get('unit_of_measurement') min_order = request.POST.get('min_order') if not min_order: min_order = 1 visible = request.POST.get('visible') photos_ids = request.POST.get('photos_ids') photos_ids_list = photos_ids.strip(',').split(',') if photos_ids else [] category = ItemCategory.objects.get(pk=category_id) if retail_price and retail_price < wholesale_price: error = _("Retail price cannot be smaller than wholesale price.") context = self.get_context_data(**kwargs) context['error'] = error return render(request, self.template_name, context) if item_id: item = get_object_or_404(Item, pk=item_id) if getattr(settings, 'IS_PROVIDER', False): if item.is_retailed: error = _("Items already imported by some retailers. Delete and start again.") context = self.get_context_data(**kwargs) context['error'] = error return render(request, self.template_name, context) item.on_sale = False if item.category != category: item.category.items_count -= 1 item.category.save() else: if not config.is_pro_version and config.max_products == Item.objects.filter(in_trash=False).count(): error = _("Items cannot be added because the limit of %d items is reached." % config.max_products) context = self.get_context_data(**kwargs) context['error'] = error return render(request, self.template_name, context) category.items_count = category.item_set.all().count() + 1 item = Item(units_sold_history=[0]) # if item.id is not None and item.provider != operator: # return HttpResponseForbidden("You don't have permission to access this resource.") item.name = name item.slug = slugify(name) item.brand = brand item.summary = summary item.description = description item.badge_text = badge_text item.category = category item.reference = reference item.original_id = original_id item.size = size item.weight = weight item.has_background_image = has_background_image item.min_order = min_order item.unit_of_measurement = unit_of_measurement item.tags = item.slug.replace('-', ' ') try: item.stock = int(stock.strip()) except: item.stock = 0 if getattr(settings, 'IS_PROVIDER', False): item.wholesale_price = wholesale_price if max_price: item.max_price = float(max_price.strip()) item.photos = [] if len(photos_ids_list) == 0: item.visible = False # Items without photo are hidden else: item.visible = True if visible else False # Items with photo has visibility chosen by user for photo_id in photos_ids_list: if photo_id: try: photo = Photo.objects.get(pk=photo_id) item.photos.append(photo) except: pass if retail_price: item.retail_price = retail_price item.provider = service item.save() category.save() if item_id: next_url = reverse('items:change_item', args=(item_id, )) messages.success(request, _("Items %s successfully updated." % item.name)) else: next_url = reverse('items:item_list') messages.success(request, _("Items %s successfully created." % item.name)) mark_duplicates(item) next_url = append_auth_tokens(next_url, request) return HttpResponseRedirect(next_url) else: context = self.get_context_data(**kwargs) admin_form = helpers.AdminForm(form, list(item_admin.get_fieldsets(self.request)), item_admin.get_prepopulated_fields(self.request), item_admin.get_readonly_fields(self.request)) context['model_admin_form'] = admin_form messages.error(request, _("Items was not created. One ore more fields were invalid.")) return render(request, self.template_name, context)
def graph_queryset(modeladmin, request, queryset): MForm = graph_form_factory(modeladmin.model) graph_type = table = None extra = '{}' try: adminaction_requested.send(sender=modeladmin.model, action='graph_queryset', request=request, queryset=queryset, modeladmin=modeladmin) except ActionInterrupted as e: messages.error(request, str(e)) return if 'apply' in request.POST: form = MForm(request.POST) if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='graph_queryset', request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return try: x = form.cleaned_data['axes_x'] # y = form.cleaned_data['axes_y'] graph_type = form.cleaned_data['graph_type'] field, model, direct, m2m = modeladmin.model._meta.get_field_by_name( x) cc = queryset.values_list(x).annotate(Count(x)).order_by() if isinstance(field, ForeignKey): data_labels = [] for value, cnt in cc: data_labels.append( str(field.rel.to.objects.get(pk=value))) elif isinstance(field, BooleanField): data_labels = [str(l) for l, v in cc] elif hasattr(modeladmin.model, 'get_%s_display' % field.name): data_labels = [] for value, cnt in cc: data_labels.append( force_unicode(dict(field.flatchoices).get( value, value), strings_only=True)) else: data_labels = [str(l) for l, v in cc] data = [v for l, v in cc] if graph_type == 'BarChart': table = [[10, 20]] extra = """{seriesDefaults:{renderer:$.jqplot.BarRenderer, rendererOptions: {fillToZero: true, barDirection: 'horizontal'}, shadowAngle: -135, }, series:[%s], axes: {yaxis: {renderer: $.jqplot.CategoryAxisRenderer, ticks: %s}, xaxis: {pad: 1.05, tickOptions: {formatString: '%%d'}} } }""" % (json.dumps(data_labels), json.dumps(data_labels)) elif graph_type == 'PieChart': table = [zip(data_labels, data)] extra = """{seriesDefaults: {renderer: jQuery.jqplot.PieRenderer, rendererOptions: {fill: true, showDataLabels: true, sliceMargin: 4, lineWidth: 5}}, legend: {show: true, location: 'e'}}""" except Exception as e: messages.error(request, 'Unable to produce valid data: %s' % str(e)) else: adminaction_end.send(sender=modeladmin.model, action='graph_queryset', request=request, queryset=queryset, modeladmin=modeladmin, form=form) elif request.method == 'POST': # total = queryset.all().count() initial = { helpers.ACTION_CHECKBOX_NAME: request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across', 0) } form = MForm(initial=initial) else: initial = { helpers.ACTION_CHECKBOX_NAME: request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across', 0) } form = MForm(initial=initial) adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media ctx = { 'adminform': adminForm, 'action': 'graph_queryset', 'opts': modeladmin.model._meta, 'title': u"Graph %s" % force_unicode(modeladmin.opts.verbose_name_plural), 'app_label': queryset.model._meta.app_label, 'media': media, 'extra': extra, 'as_json': json.dumps(table), 'graph_type': graph_type } return render_to_response('adminactions/charts.html', RequestContext(request, ctx))
def change_view(self, request, object_id, form_url='', extra_context=None): """ The 'change' admin view for this model. This follows closely the base implementation from Django 1.4's django.contrib.admin.options.ModelAdmin, with the explicitly marked modifications. """ # pylint: disable-msg=C0103 model = self.model opts = model._meta obj = self.get_object(request, unquote(object_id)) if not self.has_change_permission(request, obj): raise PermissionDenied #### begin modification #### # make sure that the user has a full session length time for the current # edit activity request.session.set_expiry(settings.SESSION_COOKIE_AGE) #### end modification #### if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_unicode(opts.verbose_name), 'key': escape(object_id) }) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view( request, form_url=reverse('admin:%s_%s_add' % (opts.app_label, opts.module_name), current_app=self.admin_site.name)) ModelForm = self.get_form(request, obj) formsets = [] inline_instances = self.get_inline_instances(request) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=True) else: form_validated = False new_object = obj if form_validated: #### begin modification #### self.save_model(request, new_object, form, True) #### end modification #### change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form = ModelForm(instance=obj) #### begin modification #### media = self.media or [] #### end modification #### inline_admin_formsets = [] #### begin modification #### adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = media + adminForm.media #### end modification #### context = { 'title': _('Change %s') % force_unicode(opts.verbose_name), 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': "_popup" in request.REQUEST or \ "_popup_o2m" in request.REQUEST, 'media': media, 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'app_label': opts.app_label, 'kb_link': settings.KNOWLEDGE_BASE_URL, 'comp_name': _('%s') % force_unicode(opts.verbose_name), } context.update(extra_context or {}) return self.render_change_form(request, context, change=True, obj=obj, form_url=form_url)
def history_form_view(self, request, object_id, version_id): original_opts = self.model._meta model = getattr( self.model, self.model._meta.simple_history_manager_attribute).model obj = get_object_or_404(model, **{ original_opts.pk.attname: object_id, 'history_id': version_id, }).instance obj._state.adding = False if not self.has_change_permission(request, obj): raise PermissionDenied formsets = [] form_class = self.get_form(request, obj) if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=obj) if form.is_valid(): new_object = self.save_form(request, form, change=True) self.save_model(request, new_object, form, change=True) form.save_m2m() self.log_change(request, new_object, self.construct_change_message( request, form, formsets)) return self.response_change(request, new_object) else: form = form_class(instance=obj) admin_form = helpers.AdminForm( form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self, ) try: model_name = original_opts.model_name except AttributeError: # Django < 1.7 model_name = original_opts.module_name url_triplet = self.admin_site.name, original_opts.app_label, model_name context = { 'title': _('Revert %s') % force_text(obj), 'adminform': admin_form, 'object_id': object_id, 'original': obj, 'is_popup': False, 'media': mark_safe(self.media + admin_form.media), 'errors': helpers.AdminErrorList(form, formsets), 'app_label': model._meta.app_label, 'original_opts': original_opts, 'changelist_url': reverse('%s:%s_%s_changelist' % url_triplet), 'change_url': reverse('%s:%s_%s_change' % url_triplet, args=(obj.pk,)), 'history_url': reverse('%s:%s_%s_history' % url_triplet, args=(obj.pk,)), # Context variables copied from render_change_form 'add': False, 'change': True, 'has_add_permission': self.has_add_permission(request), 'has_change_permission': self.has_change_permission(request, obj), 'has_delete_permission': self.has_delete_permission(request, obj), 'has_file_field': True, 'has_absolute_url': False, 'form_url': '', 'opts': model._meta, 'content_type_id': ContentType.objects.get_for_model( self.model).id, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'root_path': getattr(self.admin_site, 'root_path', None), } return render(request, template_name=self.object_history_form_template, dictionary=context, current_app=self.admin_site.name)
def _match_view(self, request, object_id, extra_context=None): """ The 'match list' view for this model. """ from django.contrib.admin.views.main import ERROR_FLAG if self.match_parent_model is None: match_parent_sitemodel = self else: match_parent_sitemodel = self.admin_site._registry[ self.match_parent_model] match_child_sitemodel = self.admin_site._registry[ self.match_child_model] opts = match_child_sitemodel.model._meta # opts = self.model._meta app_label = opts.app_label if not self.has_permission(request, 'match'): raise PermissionDenied match_list_display = self.match_list_display match_list_display_links = match_child_sitemodel.get_list_display_links( request, match_list_display) match_list_filter = match_child_sitemodel.get_list_filter(request) match_top_filters = match_child_sitemodel.get_top_filters(request) match_date_hierarchy = self.match_date_hierarchy match_list_search_fields = self.match_list_search_fields match_list_select_related = self.match_list_select_related match_list_per_page = self.match_list_per_page match_list_max_show_all = self.match_list_max_show_all match_list_editable = self.match_list_editable to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) obj = self.get_object(request, unquote(object_id), to_field) if not self.has_permission(request, 'match', obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) MatchList = self.get_matchlist(request) try: cl = MatchList(request, match_list_display, match_list_display_links, match_list_filter, match_top_filters, match_date_hierarchy, match_list_search_fields, match_list_select_related, match_list_per_page, match_list_max_show_all, match_list_editable, match_parent_sitemodel, object_id, match_child_sitemodel) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main # changelist page, without parameters, and pass an 'invalid=1' # parameter via the query string. If wacky parameters were given # and the 'invalid=1' parameter was already in the query string, # something is screwed up with the database, so display an error # page. if ERROR_FLAG in request.GET.keys(): return SimpleTemplateResponse('admin/invalid_setup.html', { 'title': _('Database error'), }) return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') # If we're allowing changelist editing, we need to construct a formset # for the changelist given all the fields to be edited. Then we'll # use the formset to validate/process POSTed data. formset = cl.formset = None # Handle POSTed bulk-edit data. if request.method == 'POST' and '_save' in request.POST: FormSet = self.get_matchlist_formset(request) formset = cl.formset = FormSet(request.POST, request.FILES, queryset=self.get_queryset(request)) if formset.is_valid(): matches = self.build_matches(formset.forms) try: self.save_matches(obj, matches) msg = "Matched successfully." self.message_user(request, msg, messages.SUCCESS) except ValidationError as ex: for message in ex.messages: self.message_user(request, message, messages.ERROR) return HttpResponseRedirect(request.get_full_path()) # Handle GET -- construct a formset for display. elif cl.list_editable: FormSet = self.get_matchlist_formset(request) formset = cl.formset = FormSet(queryset=cl.result_list) ModelForm = self.get_form(request, obj) form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm( form, list(self.get_match_parent_fieldsets(request, obj)), self.get_prepopulated_fields(request, obj), self.get_match_parent_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media # Build the list of media to be used by the formset. if formset: media += self.media + formset.media else: media += self.media action_form = None selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) ModelForm = self.get_form(request, obj) form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) context = dict( self.admin_site.each_context(request), title=_('Change %s') % force_text(opts.verbose_name), adminform=adminForm, change=True, object_id=object_id, original=obj, save_as=False, change_actions=False, show_save=False, show_save_and_continue=False, has_add_permission=False, has_change_permission=True, has_delete_permission=False, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=[], errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), module_name=force_text(opts.verbose_name_plural), selection_note=_('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)}, selection_note_all=selection_note_all % {'total_count': cl.result_count}, cl=cl, opts=cl.opts, action_form=action_form, actions_on_top=self.actions_on_top, actions_on_bottom=self.actions_on_bottom, actions_selection_counter=self.actions_selection_counter, ) context.update(self.get_model_extra_context(request)) context.update(extra_context or {}) request.current_app = self.admin_site.name return TemplateResponse(request, 'finance/match.html', context)
def base_export( modeladmin, request, queryset, title, impl, # noqa name, action_short_description, template, form_class, ): """ export a queryset to csv file """ opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label, get_permission_codename('adminactions_export', opts)) if not request.user.has_perm(perm): messages.error( request, _('Sorry you do not have rights to execute this action')) return try: adminaction_requested.send(sender=modeladmin.model, action=name, request=request, queryset=queryset, modeladmin=modeladmin) except ActionInterrupted as e: messages.error(request, str(e)) return cols = [(f.name, f.verbose_name) for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': get_action(request), 'columns': [x for x, v in cols] } if initial["action"] == "export_as_csv": initial.update( getattr(settings, "ADMINACTIONS_CSV_OPTIONS_DEFAULT", {})) if 'apply' in request.POST: form = form_class(request.POST) form.fields['columns'].choices = cols if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action=name, request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return if hasattr(modeladmin, 'get_%s_filename' % name): filename = modeladmin.get_export_as_csv_filename( request, queryset) else: filename = None try: response = impl(queryset, fields=form.cleaned_data['columns'], header=form.cleaned_data.get('header', False), filename=filename, options=form.cleaned_data) except Exception as e: messages.error(request, "Error: (%s)" % str(e)) else: adminaction_end.send(sender=modeladmin.model, action=name, request=request, queryset=queryset, modeladmin=modeladmin, form=form) return response else: form = form_class(initial=initial) form.fields['columns'].choices = cols adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media # tpl = 'adminactions/export_csv.html' ctx = { 'adminform': adminForm, 'change': True, 'action_short_description': action_short_description, 'title': title, 'is_popup': False, 'save_as': False, 'has_delete_permission': False, 'has_add_permission': False, 'has_change_permission': True, 'queryset': queryset, 'opts': queryset.model._meta, 'app_label': queryset.model._meta.app_label, 'media': mark_safe(media) } ctx.update(modeladmin.admin_site.each_context(request)) return render(request, template, ctx)
def merge(modeladmin, request, queryset): """ Merge two model instances. Move all foreign keys. """ def raw_widget(field, **kwargs): """ force all fields as not required""" kwargs['widget'] = TextInput({'class': 'raw-value', 'readonly': 'readonly'}) kwargs['widget'] = TextInput({'class': 'raw-value', 'size': '30'}) return field.formfield(**kwargs) # Allows to specified a custom Form in the ModelAdmin # MForm = getattr(modeladmin, 'merge_form', MergeForm) merge_form = getattr(modeladmin, 'merge_form', MergeForm) MForm = modelform_factory(modeladmin.model, form=merge_form, formfield_callback=raw_widget) OForm = modelform_factory(modeladmin.model, formfield_callback=raw_widget) tpl = 'adminactions/merge.html' ctx = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'fields': [f for f in queryset.model._meta.fields if not f.primary_key and f.editable], 'app_label': queryset.model._meta.app_label, 'result': '', 'opts': queryset.model._meta} if 'preview' in request.POST: master = queryset.get(pk=request.POST.get('master_pk')) original = clone_instance(master) other = queryset.get(pk=request.POST.get('other_pk')) formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)]) with transaction.commit_manually(): form = MForm(request.POST, instance=master) other.delete() form_is_valid = form.is_valid() transaction.rollback() if form_is_valid: ctx.update({'original': original}) tpl = 'adminactions/merge_preview.html' elif 'apply' in request.POST: master = queryset.get(pk=request.POST.get('master_pk')) other = queryset.get(pk=request.POST.get('other_pk')) formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)]) with transaction.commit_manually(): form = MForm(request.POST, instance=master) other.delete() if form.is_valid(): form.save() transaction.commit() return HttpResponseRedirect(request.path) else: messages.error(request, form.errors) transaction.rollback() else: try: master, other = queryset.all() except ValueError: messages.error(request, _('Please select exactly 2 records')) return initial = {'_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': 0, 'generic': MergeForm.GEN_IGNORE, 'dependencies': MergeForm.DEP_MOVE, 'action': 'merge', 'master_pk': master.pk, 'other_pk': other.pk} formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)]) form = MForm(initial=initial, instance=master) adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media ctx.update({'adminform': adminForm, 'formset': formset, 'media': mark_safe(media), 'master': master, 'other': other}) return render_to_response(tpl, RequestContext(request, ctx))
def export_delete_tree(modeladmin, request, queryset): # noqa """ Export as fixture selected queryset and all the records that belong to. That mean that dump what will be deleted if the queryset was deleted """ opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label, get_permission_codename('adminactions_export', opts)) if not request.user.has_perm(perm): messages.error( request, _('Sorry you do not have rights to execute this action')) return try: adminaction_requested.send(sender=modeladmin.model, action='export_delete_tree', request=request, queryset=queryset, modeladmin=modeladmin) except ActionInterrupted as e: messages.error(request, str(e)) return initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': get_action(request), 'serializer': 'json', 'indent': 4 } if 'apply' in request.POST: form = FixtureOptions(request.POST) if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='export_delete_tree', request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return try: collect_related = form.cleaned_data.get('add_foreign_keys') using = router.db_for_write(modeladmin.model) c = Collector(using) c.collect(queryset, collect_related=collect_related) data = [] for model, instances in list(c.data.items()): data.extend(instances) adminaction_end.send(sender=modeladmin.model, action='export_delete_tree', request=request, queryset=queryset, modeladmin=modeladmin, form=form) if hasattr(modeladmin, 'get_export_delete_tree_filename'): filename = modeladmin.get_export_delete_tree_filename( request, queryset) else: filename = None return _dump_qs(form, queryset, data, filename) except AttributeError as e: messages.error(request, str(e)) return HttpResponseRedirect(request.path) else: form = FixtureOptions(initial=initial) adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, model_admin=modeladmin) media = modeladmin.media + adminForm.media tpl = 'adminactions/export_fixture.html' ctx = { 'adminform': adminForm, 'change': True, 'action_short_description': export_delete_tree.short_description, 'title': u"%s (%s)" % ( export_delete_tree.short_description.capitalize(), modeladmin.opts.verbose_name_plural, ), 'is_popup': False, 'save_as': False, 'has_delete_permission': False, 'has_add_permission': False, 'has_change_permission': True, 'queryset': queryset, 'opts': queryset.model._meta, 'app_label': queryset.model._meta.app_label, 'media': mark_safe(media) } ctx.update(modeladmin.admin_site.each_context(request)) return render(request, tpl, ctx)
def view_view(self, request, object_id, extra_context=None): "The 'View' admin view for this model." obj = self.get_object(request, unquote(object_id)) if self.has_change_permission(request, obj): request.feed_upload_status.update_with_object(obj, fail_silently=True) model = self.model opts = model._meta try: obj = self.queryset(request).get(pk=unquote(object_id)) except model.DoesNotExist: # Don't raise Http404 just yet, because we haven't checked # permissions yet. We don't want an unauthenticated user to be able # to determine whether a given object exists. obj = None #if not self.has_change_permission(request, obj): # raise PermissionDenied if obj is None: raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_unicode(opts.verbose_name), 'key': escape(object_id)}) if request.method == 'POST' and request.POST.has_key("_saveasnew"): return self.add_view(request, form_url='../add/') ModelForm = self.get_form(request, obj) formsets = [] form = ModelForm(instance=obj) prefixes = {} for FormSet in self.get_view_formsets(request, obj): prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=obj, prefix=prefix) formsets.append(formset) adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(self.view_inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request, obj)) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media registry = [] for r in self.admin_site._registry: registry.append(r._meta.verbose_name.lower()) context = { 'title': _('View %s') % force_unicode(opts.verbose_name), 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'cloneable': obj.cloneable(), 'is_popup': request.REQUEST.has_key('_popup'), 'tabbed': self.tabbed, 'tab_name': self.tab_name, 'media': mark_safe(media), 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'root_path': reverse('admin:index'), 'app_label': opts.app_label, 'registry': registry, } context.update(extra_context or {}) return self.render_view_view(request, context, obj=obj)
def mass_change_view(self, request, comma_separated_object_ids, extra_context=None): """The 'mass change' admin view for this model.""" global new_object model = self.model opts = model._meta general_error = None # Allow model to hide some fields for mass admin exclude_fields = getattr(self.admin_obj, "massadmin_exclude", ()) queryset = getattr(self.admin_obj, "massadmin_queryset", self.get_queryset)(request) object_ids = comma_separated_object_ids.split(',') object_id = object_ids[0] try: obj = queryset.get(pk=unquote(object_id)) except model.DoesNotExist: obj = None # TODO It's necessary to check permission and existence for all object if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) ModelForm = self.get_form(request, obj) formsets = [] errors, errors_list = None, None mass_changes_fields = request.POST.getlist("_mass_change") if request.method == 'POST': # commit only when all forms are valid try: with transaction.atomic(): objects_count = 0 changed_count = 0 objects = queryset.filter(pk__in=object_ids) for obj in objects: objects_count += 1 form = ModelForm(request.POST, request.FILES, instance=obj) exclude = [] for fieldname, field in list(form.fields.items()): if fieldname not in mass_changes_fields: exclude.append(fieldname) for exclude_fieldname in exclude: del form.fields[exclude_fieldname] if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=True) else: form_validated = False new_object = obj prefixes = {} for FormSet in get_formsets(self, request, new_object): prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) if prefix in mass_changes_fields: formset = FormSet(request.POST, request.FILES, instance=new_object, prefix=prefix) formsets.append(formset) if all_valid(formsets) and form_validated: # self.admin_obj.save_model(request, new_object, form, change=True) self.save_model(request, new_object, form, change=True) form.save_m2m() for formset in formsets: self.save_formset(request, form, formset, change=True) change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) changed_count += 1 if changed_count == objects_count: return self.response_change(request, new_object) else: errors = form.errors errors_list = helpers.AdminErrorList(form, formsets) # Raise error for rollback transaction in atomic block raise ValidationError("Not all forms is correct") except: general_error = sys.exc_info()[1] form = ModelForm(instance=obj) form._errors = errors prefixes = {} for FormSet in get_formsets(self, request, obj): prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=obj, prefix=prefix) formsets.append(formset) adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self.admin_obj) media = self.media + adminForm.media # We don't want the user trying to mass change unique fields! unique_fields = [] try: # Django >= 1.9 fields = model._meta.get_fields() except: fields = model._meta.get_all_field_names() for field_name in fields: try: field = model._meta.get_field(field_name) if field.unique: unique_fields.append(field_name) except: pass # Buggy! Use at your own risk #inline_admin_formsets = [] # for inline, formset in zip(self.inline_instances, formsets): # fieldsets = list(inline.get_fieldsets(request, obj)) # inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets) # inline_admin_formsets.append(inline_admin_formset) # media = media + inline_admin_formset.media context = { **self.admin_site.each_context(request), 'title': _('Change %s') % force_text(opts.verbose_name), 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'unique_fields': unique_fields, 'exclude_fields': exclude_fields, 'is_popup': '_popup' in request.GET or '_popup' in request.POST, 'media': mark_safe(media), #'inline_admin_formsets': inline_admin_formsets, 'errors': errors_list, 'general_error': general_error, 'app_label': opts.app_label, 'object_ids': comma_separated_object_ids, 'mass_changes_fields': mass_changes_fields, } context.update(extra_context or {}) return self.render_mass_change_form(request, context, change=True, obj=obj)
def history_form_view(self, request, object_id, version_id, extra_context=None): request.current_app = self.admin_site.name original_opts = self.model._meta model = getattr( self.model, self.model._meta.simple_history_manager_attribute).model obj = get_object_or_404( model, **{ original_opts.pk.attname: object_id, "history_id": version_id }).instance obj._state.adding = False if not self.has_change_permission(request, obj): raise PermissionDenied if SIMPLE_HISTORY_EDIT: change_history = True else: change_history = False if "_change_history" in request.POST and SIMPLE_HISTORY_EDIT: history = utils.get_history_manager_for_model(obj) obj = history.get(pk=version_id).instance formsets = [] form_class = self.get_form(request, obj) if request.method == "POST": form = form_class(request.POST, request.FILES, instance=obj) if form.is_valid(): new_object = self.save_form(request, form, change=True) self.save_model(request, new_object, form, change=True) form.save_m2m() self.log_change( request, new_object, self.construct_change_message(request, form, formsets), ) return self.response_change(request, new_object) else: form = form_class(instance=obj) admin_form = helpers.AdminForm( form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self, ) model_name = original_opts.model_name url_triplet = self.admin_site.name, original_opts.app_label, model_name context = { "title": self.history_form_view_title(obj), "adminform": admin_form, "object_id": object_id, "original": obj, "is_popup": False, "media": mark_safe(self.media + admin_form.media), "errors": helpers.AdminErrorList(form, formsets), "app_label": original_opts.app_label, "original_opts": original_opts, "changelist_url": reverse("%s:%s_%s_changelist" % url_triplet), "change_url": reverse("%s:%s_%s_change" % url_triplet, args=(obj.pk, )), "history_url": reverse("%s:%s_%s_history" % url_triplet, args=(obj.pk, )), "change_history": change_history, "revert_disabled": self.revert_disabled, # Context variables copied from render_change_form "add": False, "change": True, "has_add_permission": self.has_add_permission(request), "has_change_permission": self.has_change_permission(request, obj), "has_delete_permission": self.has_delete_permission(request, obj), "has_file_field": True, "has_absolute_url": False, "form_url": "", "opts": model._meta, "content_type_id": self.content_type_model_cls.objects.get_for_model(self.model).id, "save_as": self.save_as, "save_on_top": self.save_on_top, "root_path": getattr(self.admin_site, "root_path", None), } context.update(self.admin_site.each_context(request)) context.update(extra_context or {}) extra_kwargs = {} return self.render_history_view(request, self.object_history_form_template, context, **extra_kwargs)
def _django_change_view(self, request, object_id, extra_context=None): "The 'change' admin view for this model." model = self.model opts = model._meta obj = self.get_object(request, unquote(object_id)) previous_template = obj.template # STOAT: Save previous template if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_unicode(opts.verbose_name), 'key': escape(object_id) }) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view(request, form_url='../add/') ModelForm = self.get_form(request, obj) formsets = [] if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=True) else: form_validated = False new_object = obj prefixes = {} if previous_template == new_object.template: # STOAT: Template check for FormSet, inline in zip( self.get_formsets(request, new_object), self._create_inlines(obj)): # STOAT: _create_inlines prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(request.POST, request.FILES, instance=new_object, prefix=prefix, queryset=inline.queryset(request)) formsets.append(formset) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, change=True) form.save_m2m() for formset in formsets: self.save_formset(request, form, formset, change=True) change_message = self.construct_change_message( request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form = ModelForm(instance=obj) prefixes = {} for FormSet, inline in zip( self.get_formsets(request, obj), self._create_inlines(obj)): # STOAT: _create_inlines prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=obj, prefix=prefix, queryset=inline.queryset(request)) formsets.append(formset) adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(self._create_inlines(obj), formsets): # STOAT: _create_inlines fieldsets = list(inline.get_fieldsets(request, obj)) readonly = list(inline.get_readonly_fields(request, obj)) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets, readonly, model_admin=self) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media media = media + extra_context.pop('media') # STOAT context = { 'title': _('Change %s') % force_unicode(opts.verbose_name), 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': "_popup" in request.REQUEST, 'media': mark_safe(media), 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'root_path': self.admin_site.root_path, 'app_label': opts.app_label, } context.update(extra_context or {}) return self.render_change_form(request, context, change=True, obj=obj)
def history_form_view(self, request, object_id, version_id): request.current_app = self.admin_site.name original_opts = self.model._meta model = getattr( self.model, self.model._meta.simple_history_manager_attribute).model historical_obj = get_object_or_404( model, **{ original_opts.pk.attname: object_id, 'history_id': version_id, }) obj = historical_obj.instance obj._state.adding = False if not self.has_change_permission(request, obj): raise PermissionDenied if SIMPLE_HISTORY_EDIT: change_history = True else: change_history = False if '_change_history' in request.POST and SIMPLE_HISTORY_EDIT: obj = obj.history.get(pk=version_id).instance formsets = [] form_class = self.get_form(request, obj) if request.method == 'POST': form = form_class(request.POST, request.FILES, instance=obj) if form.is_valid(): new_object = self.save_form(request, form, change=True) self.save_model(request, new_object, form, change=True) form.save_m2m() self.log_change( request, new_object, self.construct_change_message(request, form, formsets)) return self.response_change(request, new_object) else: form = form_class(instance=obj) admin_form = helpers.AdminForm( form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self, ) model_name = original_opts.model_name url_triplet = self.admin_site.name, original_opts.app_label, model_name inline_instances = self.get_inline_instances(request, obj) prefixes = {} formset = [] historical_date = historical_obj.history_date adjusted_historical_date = historical_date + datetime.timedelta( seconds=5) for FormSet, inline in self.get_admin_formsets_with_inline(*[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]) inline_qs = inline.get_queryset(request) inline_ids = inline_qs.values_list('id', flat=True) history_inline_model = inline_qs.first().history.model historical_ids = history_inline_model.objects\ .filter(id__in=inline_ids, history_date__lte=adjusted_historical_date)\ .order_by('-history_date')[:inline_qs.count()]\ .values_list('history_id', flat=True) historical_queryset = history_inline_model.objects.filter( history_id__in=historical_ids) formset_params = { 'instance': obj, 'prefix': prefix, 'queryset': historical_queryset, } if request.method == 'POST': formset_params.update({ 'data': request.POST.copy(), 'files': request.FILES, 'save_as_new': '_saveasnew' in request.POST }) formset.append(FormSet(**formset_params)) inline_formsets = self.get_admin_inline_formsets( request, formset, inline_instances, obj) context = { 'title': _('Revert %s') % force_text(obj), 'adminform': admin_form, 'object_id': object_id, 'original': obj, 'is_popup': False, 'media': mark_safe(self.media + admin_form.media), 'errors': helpers.AdminErrorList(form, formsets), 'app_label': original_opts.app_label, 'original_opts': original_opts, 'changelist_url': reverse('%s:%s_%s_changelist' % url_triplet), 'change_url': reverse('%s:%s_%s_change' % url_triplet, args=(obj.pk, )), 'history_url': reverse('%s:%s_%s_history' % url_triplet, args=(obj.pk, )), 'change_history': change_history, 'inline_admin_formsets': inline_formsets, # Context variables copied from render_change_form 'add': False, 'change': True, 'has_add_permission': self.has_add_permission(request), 'has_change_permission': self.has_change_permission(request, obj), 'has_delete_permission': self.has_delete_permission(request, obj), 'has_file_field': True, 'has_absolute_url': False, 'form_url': '', 'opts': model._meta, 'content_type_id': ContentType.objects.get_for_model(self.model).id, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'root_path': getattr(self.admin_site, 'root_path', None), } extra_kwargs = {} if get_complete_version() < (1, 8): extra_kwargs['current_app'] = request.current_app return render(request, self.object_history_form_template, context, **extra_kwargs)
def change_view(self, request, object_id, form_url='', extra_context=None): "The 'change' admin view for this model." model = self.model opts = model._meta obj = self.get_object(request, unquote(object_id)) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)}) if request.method == 'POST' and "_saveasnew" in request.POST: return self.add_view(request, form_url=reverse('admin:%s_%s_add' % (opts.app_label, opts.module_name), current_app=self.admin_site.name)) ModelForm = self.get_form(request, obj) formsets = [] inline_instances = self.get_inline_instances(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=True) else: form_validated = False new_object = obj prefixes = {} for FormSet, inline in self.get_formsets_with_inlines(request, new_object): 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]) formset = FormSet(request.POST, request.FILES, instance=new_object, prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if hasattr(inline, 'inlines') and inline.inlines: self.add_nested_inline_formsets(request, inline, formset) if self.all_valid_with_nesting(formsets) and form_validated: self.save_model(request, new_object, form, True) self.save_related(request, form, formsets, True) change_message = self.construct_change_message(request, form, formsets) self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form = ModelForm(instance=obj) prefixes = {} for FormSet, inline in self.get_formsets_with_inlines(request, obj): 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]) formset = FormSet(instance=obj, prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if hasattr(inline, 'inlines') and inline.inlines: self.add_nested_inline_formsets(request, inline, formset) adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.get_prepopulated_fields(request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request, obj)) readonly = list(inline.get_readonly_fields(request, obj)) prepopulated = dict(inline.get_prepopulated_fields(request, obj)) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets, prepopulated, readonly, model_admin=self) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media if hasattr(inline, 'inlines') and inline.inlines: other_media = self.wrap_nested_inline_formsets(request, inline, formset) if other_media is not None: media += other_media context = { 'title': _('Change %s') % force_text(opts.verbose_name), 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': "_popup" in request.GET, 'media': media, 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'app_label': opts.app_label, } context.update(self.admin_site.each_context(request)) context.update(extra_context or {}) return self.render_change_form(request, context, change=True, obj=obj, form_url=form_url)
def _changeform_view(self, request, object_id, form_url, extra_context): add = object_id is None model = self.model opts = model._meta if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id)) if request.method == 'POST': if not self.has_change_permission(request, obj): raise PermissionDenied else: if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) formsets = [] model_form = self.get_form(request, obj=obj, change=not add) if request.method == 'POST': form = model_form(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) formset_inline_tuples = zip(formsets, self.get_inline_instances(request)) formset_inline_tuples = _remove_blank_reverse_inlines( new_object, formset_inline_tuples) formsets = [t[0] for t in formset_inline_tuples] if form_validated and not formsets: self._save_object(request, new_object, form, formsets, add) return self.response_add(request, new_object) elif form_validated and all_valid(formsets): # Here is the modified code. for formset, inline in formset_inline_tuples: if not isinstance(inline, ReverseInlineModelAdmin): continue # The idea or this piece is coming from https://stackoverflow.com/questions/50910152/inline-formset-returns-empty-list-on-save. # Without this, formset.save() was returning None for forms that # haven't been modified forms = [f for f in formset] if not forms: continue obj = forms[0].save() setattr(new_object, inline.parent_fk_name, obj) self._save_object(request, new_object, form, formsets, add) for formset in formsets: self.save_formset(request, form, formset, change=not add) # self.log_addition(request, new_object) return self.response_add(request, new_object) else: # Prepare the dict of initial data from the request. # We have to special-case M2Ms as a list of comma-separated PKs. initial = dict(request.GET.items()) for k in initial: try: f = opts.get_field(k) except FieldDoesNotExist: continue if isinstance(f, models.ManyToManyField): initial[k] = initial[k].split(",") if add: form = model_form(initial=initial) 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: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=self.model(), prefix=prefix) formsets.append(formset) else: form = model_form(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields, readonly_fields=readonly_fields, model_admin=self) media = self.media + adminForm.media inline_admin_formsets = self.get_inline_formsets( request, formsets, self.get_inline_instances(request), obj) for inline_formset in inline_admin_formsets: media = media + inline_formset.media # Inherit the default context from admin_site context = self.admin_site.each_context(request) reverse_admin_context = { 'title': _( ('Change %s', 'Add %s')[add]) % force_str(opts.verbose_name), 'adminform': adminForm, # 'is_popup': '_popup' in request.REQUEST, 'is_popup': False, 'object_id': object_id, 'original': obj, 'media': mark_safe(media), 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), # 'root_path': self.admin_site.root_path, 'app_label': opts.app_label, } context.update(reverse_admin_context) context.update(extra_context or {}) return self.render_change_form( request, context, form_url=form_url, add=add, change=not add, obj=obj, )
def render_revision_form(self, request, obj, version, context, revert=False, recover=False): """Renders the object revision form.""" model = self.model opts = model._meta object_id = obj.pk # Generate the model form. ModelForm = self.get_form(request, obj) formsets = [] if request.method == "POST": # This section is copied directly from the model admin change view # method. Maybe one day there will be a hook for doing this better. form = ModelForm(request.POST, request.FILES, instance=obj, initial=self.get_revision_form_data(request, obj, version)) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=True) # HACK: If the value of a file field is None, remove the file from the model. for field in new_object._meta.fields: if isinstance(field, models.FileField) and field.name in form.cleaned_data and form.cleaned_data[field.name] is None: setattr(new_object, field.name, None) else: form_validated = False new_object = obj prefixes = {} for FormSet, inline in zip(self.get_formsets(request, new_object), self.get_inline_instances(request)): prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(request.POST, request.FILES, instance=new_object, prefix=prefix, queryset=inline.queryset(request)) self._hack_inline_formset_initial(FormSet, formset, obj, version, revert, recover) # Add this hacked formset to the form. formsets.append(formset) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, change=True) form.save_m2m() for formset in formsets: # HACK: If the value of a file field is None, remove the file from the model. related_objects = formset.save(commit=False) for related_obj, related_form in zip(related_objects, formset.saved_forms): for field in related_obj._meta.fields: if isinstance(field, models.FileField) and field.name in related_form.cleaned_data and related_form.cleaned_data[field.name] is None: setattr(related_obj, field.name, None) related_obj.save() formset.save_m2m() change_message = _(u"Reverted to previous version, saved on %(datetime)s") % {"datetime": format(version.revision.date_created, _('DATETIME_FORMAT'))} self.log_change(request, new_object, change_message) self.message_user(request, _(u'The %(model)s "%(name)s" was reverted successfully. You may edit it again below.') % {"model": force_unicode(opts.verbose_name), "name": unicode(obj)}) # Redirect to the model change form. if revert: return HttpResponseRedirect("../../") elif recover: return HttpResponseRedirect("../../%s/" % quote(object_id)) else: assert False else: # This is a mutated version of the code in the standard model admin # change_view. Once again, a hook for this kind of functionality # would be nice. Unfortunately, it results in doubling the number # of queries required to construct the formets. form = ModelForm(instance=obj, initial=self.get_revision_form_data(request, obj, version)) prefixes = {} for FormSet, inline in zip(self.get_formsets(request, obj), self.get_inline_instances(request)): # This code is standard for creating the formset. prefix = FormSet.get_default_prefix() prefixes[prefix] = prefixes.get(prefix, 0) + 1 if prefixes[prefix] != 1: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=obj, prefix=prefix, queryset=inline.queryset(request)) self._hack_inline_formset_initial(FormSet, formset, obj, version, revert, recover) # Add this hacked formset to the form. formsets.append(formset) # Generate admin form helper. adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields, self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media # Generate formset helpers. inline_admin_formsets = [] for inline, formset in zip(self.get_inline_instances(request), formsets): fieldsets = list(inline.get_fieldsets(request, obj)) readonly = list(inline.get_readonly_fields(request, obj)) prepopulated = inline.get_prepopulated_fields(request, obj) inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets, prepopulated, readonly, model_admin=self) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media # Generate the context. context.update({"adminform": adminForm, "object_id": object_id, "original": obj, "is_popup": False, "media": mark_safe(media), "inline_admin_formsets": inline_admin_formsets, "errors": helpers.AdminErrorList(form, formsets), "app_label": opts.app_label, "add": False, "change": True, "revert": revert, "recover": recover, "has_add_permission": self.has_add_permission(request), "has_change_permission": self.has_change_permission(request, obj), "has_delete_permission": self.has_delete_permission(request, obj), "has_file_field": True, "has_absolute_url": False, "ordered_objects": opts.get_ordered_objects(), "form_url": mark_safe(request.path), "opts": opts, "content_type_id": ContentType.objects.get_for_model(self.model).id, "save_as": False, "save_on_top": self.save_on_top, "changelist_url": reverse("%s:%s_%s_changelist" % (self.admin_site.name, opts.app_label, opts.module_name)), "change_url": reverse("%s:%s_%s_change" % (self.admin_site.name, opts.app_label, opts.module_name), args=(quote(obj.pk),)), "history_url": reverse("%s:%s_%s_history" % (self.admin_site.name, opts.app_label, opts.module_name), args=(quote(obj.pk),)), "recoverlist_url": reverse("%s:%s_%s_recoverlist" % (self.admin_site.name, opts.app_label, opts.module_name))}) # Render the form. if revert: form_template = self.revision_form_template or self._get_template_list("revision_form.html") elif recover: form_template = self.recover_form_template or self._get_template_list("recover_form.html") else: assert False return render_to_response(form_template, context, template.RequestContext(request))
def add_view(self, request, form_url='', extra_context=None): "The 'add' admin view for this model." model = self.model opts = model._meta if not self.has_add_permission(request): raise PermissionDenied model_form = self.get_form(request) formsets = [] if request.method == 'POST': form = model_form(request.POST, request.FILES) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=False) else: form_validated = False new_object = self.model() 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: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(data=request.POST, files=request.FILES, instance=new_object, save_as_new="_saveasnew" in request.POST, prefix=prefix) formsets.append(formset) if all_valid(formsets) and form_validated: # Here is the modified code. for formset, inline in zip(formsets, self.get_inline_instances(request)): if not isinstance(inline, ReverseInlineModelAdmin): continue formsetresults = formset.save() #make sure that we have some results from formset.save() #could be empty if the formset is unchanged (with all default value) #if not empty, we create a new object from the formset data if (len(formsetresults) > 0): obj = formsetresults[0] setattr(new_object, inline.parent_fk_name, obj) #if it is empty, we create a new object with all default value else: field = next((f for f in new_object._meta.fields if f.name == formset.parent_fk_name), None) #create the related model with all default value obj = field.related_model.objects.create() setattr(new_object, inline.parent_fk_name, obj) self.save_model(request, new_object, form, change=False) form.save_m2m() for formset in formsets: self.save_formset(request, form, formset, change=False) # self.log_addition(request, new_object) return self.response_add(request, new_object) else: # Prepare the dict of initial data from the request. # We have to special-case M2Ms as a list of comma-separated PKs. initial = dict(request.GET.items()) for k in initial: try: f = opts.get_field(k) except models.FieldDoesNotExist: continue if isinstance(f, models.ManyToManyField): initial[k] = initial[k].split(",") form = model_form(initial=initial) 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: prefix = "%s-%s" % (prefix, prefixes[prefix]) formset = FormSet(instance=self.model(), prefix=prefix) formsets.append(formset) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(self.get_inline_instances(request), formsets): fieldsets = list(inline.get_fieldsets(request)) inline_admin_formset = helpers.InlineAdminFormSet( inline, formset, fieldsets) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media context = { 'title': _('Add %s') % force_text(opts.verbose_name), 'adminform': adminForm, # 'is_popup': '_popup' in request.REQUEST, 'is_popup': False, 'show_delete': False, 'media': mark_safe(media), 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), # 'root_path': self.admin_site.root_path, 'app_label': opts.app_label, } context.update(extra_context or {}) return self.render_change_form(request, context, form_url=form_url, add=True)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None): to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_change_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) ModelForm = self.get_form(request, obj) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) if form.is_valid(): form_validated = True new_object = self.save_form(request, form, change=not add) else: form_validated = False new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request, obj)), self.get_prepopulated_fields( request, obj), self.get_readonly_fields(request, obj), model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media context = dict( self.admin_site.each_context(request), title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name), adminform=adminForm, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, media=media, inline_admin_formsets=inline_formsets, errors=helpers.AdminErrorList(form, formsets), preserved_filters=self.get_preserved_filters(request), ) # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
def add_view(self, request, form_url='', extra_context={}): "The 'add' admin view for this model." #copied from django/contrib/admin/options.py:924 at version 1.4.0 model = self.model opts = model._meta if not self.has_add_permission(request): raise PermissionDenied ModelForm = self.get_form(request) formsets = [] inline_instances = self.get_inline_instances(request) if request.method == 'POST': form = ModelForm(request.POST, request.FILES) if form.is_valid(): new_object = self.save_form(request, form, change=False) form_validated = True else: form_validated = False new_object = self.model() prefixes = {} for FormSet, inline in zip(self.get_formsets(request), inline_instances): 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]) formset = FormSet(data=request.POST, files=request.FILES, instance=new_object, save_as_new="_saveasnew" in request.POST, prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if hasattr(inline, 'inlines') and inline.inlines: self.add_recursive_inline_formsets(request, inline, formset) if self.all_valid(formsets) and form_validated: self.save_model(request, new_object, form, False) self.save_related(request, form, formsets, False) self.log_addition(request, new_object) return self.response_add(request, new_object) else: # Prepare the dict of initial data from the request. # We have to special-case M2Ms as a list of comma-separated PKs. initial = dict(request.GET.items()) for k in initial: try: f = opts.get_field(k) except FieldDoesNotExist: continue if isinstance(f, ManyToManyField): initial[k] = initial[k].split(",") form = ModelForm(initial=initial) prefixes = {} for FormSet, inline in zip(self.get_formsets(request), inline_instances): 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]) formset = FormSet(instance=self.model(), prefix=prefix, queryset=inline.get_queryset(request)) formsets.append(formset) if hasattr(inline, 'inlines') and hasattr(self, 'add_recursive_inline_formsets'): self.add_recursive_inline_formsets(request, inline, formset) adminForm = helpers.AdminForm(form, list( self.get_fieldsets(request)), self.get_prepopulated_fields(request), self.get_readonly_fields(request), model_admin=self) media = self.media + adminForm.media inline_admin_formsets = [] for inline, formset in zip(inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request)) readonly = list(inline.get_readonly_fields(request)) prepopulated = dict(inline.get_prepopulated_fields(request)) inline_admin_formset = helpers.InlineAdminFormSet( inline, formset, fieldsets, prepopulated, readonly, model_admin=self) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media if hasattr(inline, 'inlines'): media = media + self.wrap_recursive_inline_formsets(request, inline, formset) context = { 'title': _('Add %s') % force_unicode(opts.verbose_name), 'adminform': adminForm, 'is_popup': IS_POPUP_VAR in request.REQUEST, 'show_delete': False, 'media': media, 'inline_admin_formsets': inline_admin_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'app_label': opts.app_label, 'preserved_filters': self.get_preserved_filters(request), } context.update(extra_context or {}) return self.render_change_form(request, context, form_url=form_url, add=True)