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)
def _doit(): errors = {} updated = 0 for record in queryset: for field_name, value_or_func in 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)
def mass_update(modeladmin, request, queryset): """ mass update queryset """ def not_required(field, **kwargs): """ force all fields as not required""" kwargs['required'] = False return field.formfield(**kwargs) if not request.user.has_perm('adminactions_massupdate'): 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, formfield_callback=not_required) grouped = defaultdict(lambda: []) selected_fields = [] 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) updated = 0 errors = {} if validate: if need_transaction: transaction.enter_transaction_management() transaction.managed(True) for record in queryset: for field_name, value_or_func in 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) try: record.clean() record.save() except IntegrityError as e: errors[record.pk] = str(e) if need_transaction: transaction.rollback() updated = 0 break else: 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)) try: adminaction_end.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin, form=form, errors=errors, updated=updated) if need_transaction: transaction.commit() except ActionInterrupted: if need_transaction: transaction.rollback() finally: if need_transaction: transaction.leave_transaction_management() else: values = {} for field_name, value in 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']: values[field_name] = value queryset.update(**values) return HttpResponseRedirect(request.get_full_path()) else: initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': 'mass_update', '_validate': 1} form = MForm(initial=initial) for el in queryset.all()[:10]: for f in modeladmin.model._meta.fields: if hasattr(f, 'flatchoices') and f.flatchoices: grouped[f.name] = dict(getattr(f, 'flatchoices')).values() elif hasattr(f, 'choices') and f.choices: grouped[f.name] = 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, 'title': u"Mass update %s" % force_unicode(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} return render_to_response(tpl, RequestContext(request, ctx))
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 = [data] 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 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] 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)} if django.VERSION[:2] > (1, 7): ctx.update(modeladmin.admin_site.each_context(request)) else: ctx.update(modeladmin.admin_site.each_context()) return render_to_response(template, 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)} if django.VERSION[:2] > (1, 7): ctx.update(modeladmin.admin_site.each_context(request)) else: ctx.update(modeladmin.admin_site.each_context()) return render_to_response(tpl, RequestContext(request, ctx))
def export_as_fixture(modeladmin, request, queryset): initial = {'_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'serializer': 'json', 'indent': 4} opts = modeladmin.model._meta perm = "{0}.{1}".format(opts.app_label.lower(), 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 (%s)' % perm)) return try: adminaction_requested.send(sender=modeladmin.model, action='export_as_fixture', request=request, queryset=queryset, modeladmin=modeladmin) except ActionInterrupted as e: messages.error(request, str(e)) return if 'apply' in request.POST: form = FixtureOptions(request.POST) if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='export_as_fixture', request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return try: _collector = ForeignKeysCollector if form.cleaned_data.get('add_foreign_keys') else FlatCollector c = _collector(None) c.collect(queryset) adminaction_end.send(sender=modeladmin.model, action='export_as_fixture', request=request, queryset=queryset, modeladmin=modeladmin, form=form) if hasattr(modeladmin, 'get_export_as_fixture_filename'): filename = modeladmin.get_export_as_fixture_filename(request, queryset) else: filename = None return _dump_qs(form, queryset, c.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, 'title': _('Export as Fixture'), '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)} return render_to_response(tpl, RequestContext(request, ctx))
def export_delete_tree(modeladmin, request, queryset): """ 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.lower(), 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 (%s)' % perm)) 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': request.POST.get('action'), '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 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, 'title': _('Export Delete Tree'), '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)} return render_to_response(tpl, RequestContext(request, ctx))
def base_export(modeladmin, request, queryset, title, impl, name, template, form_class, ): """ export a queryset to csv file """ opts = modeladmin.model._meta perm = "{0}.{1}".format(opts.app_label.lower(), 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 (%s)' % perm)) 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] initial = {'_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'columns': [x for x, v in cols]} # initial.update(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, '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)} return render_to_response(template, RequestContext(request, ctx))
def mass_update(modeladmin, request, queryset): """ mass update queryset """ def not_required(field, **kwargs): """ force all fields as not required""" kwargs['required'] = False return field.formfield(**kwargs) if not request.user.has_perm('adminactions_massupdate'): 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, formfield_callback=not_required) grouped = defaultdict(lambda: []) selected_fields = [] 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) updated = 0 errors = {} if validate: if need_transaction: transaction.enter_transaction_management() transaction.managed(True) for record in queryset: for field_name, value_or_func in 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) try: record.clean() record.save() except IntegrityError as e: errors[record.pk] = str(e) if need_transaction: transaction.rollback() updated = 0 break else: 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)) try: adminaction_end.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin, form=form, errors=errors, updated=updated) if need_transaction: transaction.commit() except ActionInterrupted: if need_transaction: transaction.rollback() finally: if need_transaction: transaction.leave_transaction_management() else: values = {} for field_name, value in 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' ]: values[field_name] = value queryset.update(**values) return HttpResponseRedirect(request.get_full_path()) else: initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': 'mass_update', '_validate': 1 } form = MForm(initial=initial) for el in queryset.all()[:10]: for f in modeladmin.model._meta.fields: if hasattr(f, 'flatchoices') and f.flatchoices: grouped[f.name] = dict(getattr(f, 'flatchoices')).values() elif hasattr(f, 'choices') and f.choices: grouped[f.name] = 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, 'title': u"Mass update %s" % force_unicode(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 } return render_to_response(tpl, RequestContext(request, ctx))
def export_as_csv(modeladmin, request, queryset): """ export a queryset to csv file """ if not request.user.has_perm('adminactions.export'): messages.error(request, _('Sorry you do not have rights to execute this action')) return try: adminaction_requested.send(sender=modeladmin.model, action='export_as_csv', request=request, queryset=queryset) except ActionInterrupted as e: messages.error(request, str(e)) return cols = [(f.name, f.verbose_name) for f in queryset.model._meta.fields] initial = {'_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'date_format': 'd/m/Y', 'datetime_format': 'N j, Y, P', 'time_format': 'P', 'quotechar': '"', 'columns': [x for x, v in cols], 'quoting': csv.QUOTE_ALL, 'delimiter': ';', 'escapechar': '\\', } if 'apply' in request.POST: form = CSVOptions(request.POST) form.fields['columns'].choices = cols if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='export_as_csv', request=request, queryset=queryset, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return if hasattr(modeladmin, 'get_export_as_csv_filename'): filename = modeladmin.get_export_as_csv_filename(request, queryset) else: filename = "%s.csv" % queryset.model._meta.verbose_name_plural.lower().replace(" ", "_") response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = 'attachment;filename="%s"' % filename.encode('us-ascii', 'replace') try: writer = csv.writer(response, escapechar=str(form.cleaned_data['escapechar']), delimiter=str(form.cleaned_data['delimiter']), quotechar=str(form.cleaned_data['quotechar']), quoting=int(form.cleaned_data['quoting'])) if form.cleaned_data.get('header', False): writer.writerow([f for f in form.cleaned_data['columns']]) for obj in queryset: row = [] for fieldname in form.cleaned_data['columns']: value = get_field_value(obj, fieldname) if isinstance(value, datetime.datetime): value = dateformat.format(value, form.cleaned_data['datetime_format']) elif isinstance(value, datetime.date): value = dateformat.format(value, form.cleaned_data['date_format']) elif isinstance(value, datetime.time): value = dateformat.format(value, form.cleaned_data['time_format']) row.append(smart_str(value)) writer.writerow(row) except Exception as e: messages.error(request, "Error: (%s)" % str(e)) else: adminaction_end.send(sender=modeladmin.model, action='export_as_csv', request=request, queryset=queryset) return response else: form = CSVOptions(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, 'title': _('Export to CSV'), '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)} return render_to_response(tpl, RequestContext(request, ctx))
def mass_update(modeladmin, request, queryset): """ mass update queryset """ def not_required(field, **kwargs): """ force all fields as not required""" kwargs['required'] = False return field.formfield(**kwargs) opts = modeladmin.model._meta perm = "{0}.{1}".format(opts.app_label.lower(), 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 # adapted for UE: Check type of modeladmin.model to initialise form #raise Exception(modeladmin.model, type(modeladmin.model)) if modeladmin.model == machine: mass_update_form = getattr(modeladmin, 'mass_update_form', MassUpdateForm) MForm = modelform_factory(modeladmin.model, form=mass_update_form, formfield_callback=not_required) if not request.user.is_superuser: # Show only entites allowed if not superuser MForm.base_fields["entity"].queryset = entity.objects.filter(pk__in = request.user.subuser.id_entities_allowed).order_by('name').distinct() MForm.base_fields["entity"].empty_label = None MForm.base_fields["packages"].queryset = package.objects.filter(entity__pk__in = request.user.subuser.id_entities_allowed).order_by('name').distinct() MForm.base_fields["packageprofile"].queryset = packageprofile.objects.filter(entity__pk__in = request.user.subuser.id_entities_allowed).order_by('name').distinct() MForm.base_fields["timeprofile"].queryset = timeprofile.objects.filter(entity__pk__in = request.user.subuser.id_entities_allowed).order_by('name').distinct() else: # 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, 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', machines_selected = [ obj.id for obj in queryset] initial = {'_selected_action': machines_selected, 'action': 'mass_update', '_validate': 1} 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) updated = 0 errors = {} if validate: if need_transaction: transaction.enter_transaction_management() transaction.managed(True) for record in queryset: for field_name, value_or_func in 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) try: if clean: record.clean() record.save() except IntegrityError as e: errors[record.pk] = str(e) if need_transaction: transaction.rollback() updated = 0 break else: 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)) try: adminaction_end.send(sender=modeladmin.model, action='mass_update', request=request, queryset=queryset, modeladmin=modeladmin, form=form, errors=errors, updated=updated) if need_transaction: transaction.commit() except ActionInterrupted: if need_transaction: transaction.rollback() finally: if need_transaction: transaction.leave_transaction_management() else: values = {} for field_name, value in 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']: 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] = dict(getattr(f, 'flatchoices')).values() elif hasattr(f, 'choices') and f.choices: grouped[f.name] = 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, 'title': u"Mass update %s" % force_unicode(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} return render_to_response(tpl, RequestContext(request, ctx))
def export_as_csv(modeladmin, request, queryset): """ export a queryset to csv file """ if not request.user.has_perm('adminactions.export'): messages.error( request, _('Sorry you do not have rights to execute this action')) return try: adminaction_requested.send(sender=modeladmin.model, action='export_as_csv', 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] initial = { '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), 'select_across': request.POST.get('select_across') == '1', 'action': request.POST.get('action'), 'columns': [x for x, v in cols]} initial.update(csv_options_default) if 'apply' in request.POST: form = CSVOptions(request.POST) form.fields['columns'].choices = cols if form.is_valid(): try: adminaction_start.send(sender=modeladmin.model, action='export_as_csv', request=request, queryset=queryset, modeladmin=modeladmin, form=form) except ActionInterrupted as e: messages.error(request, str(e)) return if hasattr(modeladmin, 'get_export_as_csv_filename'): filename = modeladmin.get_export_as_csv_filename( request, queryset) else: filename = None try: response = _export_as_csv(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='export_as_csv', request=request, queryset=queryset, modeladmin=modeladmin, form=form) return response else: form = CSVOptions(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, 'title': _('Export as CSV'), '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)} return render_to_response(tpl, RequestContext(request, ctx))
def graph_queryset(modeladmin, request, queryset): MForm = graph_form_factory(modeladmin.model) graph_type = table = None 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] table = zip(data_labels, data) 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, 'app_label': queryset.model._meta.app_label, 'media': media, 'as_json': json.dumps(table), 'graph_type': graph_type} return render_to_response('adminactions/charts.html', RequestContext(request, ctx))
def mass_update(modeladmin, request, queryset): """ mass update queryset """ def not_required(field, **kwargs): """ force all fields as not required""" kwargs["required"] = False return field.formfield(**kwargs) opts = modeladmin.model._meta perm = "{0}.{1}".format(opts.app_label.lower(), 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, 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) updated = 0 errors = {} if validate: if need_transaction: transaction.enter_transaction_management() transaction.managed(True) for record in queryset: for field_name, value_or_func in 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) try: if clean: record.clean() record.save() except IntegrityError as e: errors[record.pk] = str(e) if need_transaction: transaction.rollback() updated = 0 break else: 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)) try: adminaction_end.send( sender=modeladmin.model, action="mass_update", request=request, queryset=queryset, modeladmin=modeladmin, form=form, errors=errors, updated=updated, ) if need_transaction: transaction.commit() except ActionInterrupted: if need_transaction: transaction.rollback() finally: if need_transaction: transaction.leave_transaction_management() else: values = {} for field_name, value in 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"]: 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 hasattr(f, "flatchoices") and f.flatchoices: grouped[f.name] = dict(getattr(f, "flatchoices")).values() elif hasattr(f, "choices") and f.choices: grouped[f.name] = 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, "title": u"Mass update %s" % force_unicode(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, } return render_to_response(tpl, RequestContext(request, ctx))