django-orchestra/orchestra/contrib/domains/actions.py

153 lines
6.1 KiB
Python

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 = '<a href="%(url)s" title="%(title)s">%(name)s</a>' % 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")