import copy from django.contrib import messages from django.contrib.admin import helpers from django.db.models import Q from django.db.models.functions import Concat, Coalesce from django.shortcuts import render from django.utils.safestring import mark_safe from django.utils.translation import ungettext, ugettext_lazy as _ from django.template.response import TemplateResponse from orchestra.admin.forms import adminmodelformset_factory from orchestra.admin.utils import get_object_from_url, change_url, admin_link from orchestra.utils.python import AttrDict from .forms import RecordForm, RecordEditFormSet, SOAForm from .models import Record def view_zone(modeladmin, request, queryset): zone = queryset.get() context = { 'opts': modeladmin.model._meta, 'object': zone, 'title': _("%s zone content") % zone.origin.name } return TemplateResponse(request, 'admin/domains/domain/view_zone.html', context) view_zone.url_name = 'view-zone' view_zone.short_description = _("View zone") def edit_records(modeladmin, request, queryset): selected_ids = queryset.values_list('id', flat=True) # Include subodmains queryset = queryset.model.objects.filter( Q(top__id__in=selected_ids) | Q(id__in=selected_ids) ).annotate( structured_id=Coalesce('top__id', 'id'), structured_name=Concat('top__name', 'name') ).order_by('-structured_id', 'structured_name') formsets = [] for domain in queryset.prefetch_related('records'): modeladmin_copy = copy.copy(modeladmin) modeladmin_copy.model = Record prefix = '' if domain.is_top else ' '*8 context = { 'url': change_url(domain), 'name': prefix+domain.name, 'title': '', } if domain.id not in selected_ids: context['name'] += '*' context['title'] = _("This subdomain was not explicitly selected " "but has been automatically added to this list.") link = '%(name)s' % context modeladmin_copy.verbose_name_plural = mark_safe(link) RecordFormSet = adminmodelformset_factory( modeladmin_copy, RecordForm, formset=RecordEditFormSet, extra=1, can_delete=True) formset = RecordFormSet(queryset=domain.records.all(), prefix=domain.id) formset.instance = domain formset.cls = RecordFormSet formsets.append(formset) if request.POST.get('post') == 'generic_confirmation': posted_formsets = [] all_valid = True for formset in formsets: instance = formset.instance formset = formset.cls( request.POST, request.FILES, queryset=formset.queryset, prefix=instance.id) formset.instance = instance if not formset.is_valid(): all_valid = False posted_formsets.append(formset) formsets = posted_formsets if all_valid: for formset in formsets: for form in formset.forms: form.instance.domain_id = formset.instance.id formset.save() fake_form = AttrDict({ 'changed_data': False }) change_message = modeladmin.construct_change_message(request, fake_form, [formset]) modeladmin.log_change(request, formset.instance, change_message) num = len(formsets) message = ungettext( _("Records for one selected domain have been updated."), _("Records for %i selected domains have been updated.") % num, num) modeladmin.message_user(request, message) return opts = modeladmin.model._meta context = { 'title': _("Edit records"), 'action_name': _("Edit records"), 'action_value': 'edit_records', 'display_objects': [], 'queryset': queryset, 'opts': opts, 'app_label': opts.app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'formsets': formsets, 'obj': get_object_from_url(modeladmin, request), } return render(request, 'admin/domains/domain/edit_records.html', context) def set_soa(modeladmin, request, queryset): if queryset.filter(top__isnull=False).exists(): msg = _("Set SOA on subdomains is not possible.") modeladmin.message_user(request, msg, messages.ERROR) return form = SOAForm() if request.POST.get('post') == 'generic_confirmation': form = SOAForm(request.POST) if form.is_valid(): updates = {name: value for name, value in form.cleaned_data.items() if value} change_message = _("SOA set %s") % str(updates)[1:-1] for domain in queryset: for name, value in updates.items(): if name.startswith('clear_'): name = name.replace('clear_', '') value = '' setattr(domain, name, value) modeladmin.log_change(request, domain, change_message) domain.save() num = len(queryset) msg = ungettext( _("SOA record for one domain has been updated."), _("SOA record for %s domains has been updated.") % num, num ) modeladmin.message_user(request, msg) return opts = modeladmin.model._meta context = { 'title': _("Set SOA for selected domains"), 'content_message': '', 'action_name': _("Set SOA"), 'action_value': 'set_soa', 'display_objects': [admin_link('__str__')(domain) for domain in queryset], 'queryset': queryset, 'opts': opts, 'app_label': opts.app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'form': form, 'obj': get_object_from_url(modeladmin, request), } return render(request, 'admin/orchestra/generic_confirmation.html', context) set_soa.short_description = _("Set SOA for selected domains")