2014-05-08 16:59:35 +00:00
|
|
|
from django import forms
|
|
|
|
from django.contrib import admin
|
2015-05-18 15:21:42 +00:00
|
|
|
from django.db.models.functions import Concat, Coalesce
|
2014-05-08 16:59:35 +00:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
|
2014-11-05 21:29:14 +00:00
|
|
|
from orchestra.admin import ExtendedModelAdmin
|
2014-09-26 15:05:20 +00:00
|
|
|
from orchestra.admin.utils import admin_link, change_url
|
2015-04-05 10:46:24 +00:00
|
|
|
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
2014-05-08 16:59:35 +00:00
|
|
|
from orchestra.utils import apps
|
|
|
|
|
2015-07-20 12:51:30 +00:00
|
|
|
from .actions import view_zone, edit_records, set_soa
|
2014-05-08 16:59:35 +00:00
|
|
|
from .filters import TopDomainListFilter
|
2015-07-17 13:29:29 +00:00
|
|
|
from .forms import RecordForm, RecordInlineFormSet, BatchDomainCreationAdminForm
|
2014-05-08 16:59:35 +00:00
|
|
|
from .models import Domain, Record
|
|
|
|
|
|
|
|
|
|
|
|
class RecordInline(admin.TabularInline):
|
|
|
|
model = Record
|
2015-07-17 13:29:29 +00:00
|
|
|
form = RecordForm
|
2014-05-08 16:59:35 +00:00
|
|
|
formset = RecordInlineFormSet
|
|
|
|
verbose_name_plural = _("Extra records")
|
|
|
|
|
|
|
|
|
|
|
|
class DomainInline(admin.TabularInline):
|
|
|
|
model = Domain
|
2014-10-24 11:10:30 +00:00
|
|
|
fields = ('domain_link', 'display_records', 'account_link')
|
|
|
|
readonly_fields = ('domain_link', 'display_records', 'account_link')
|
2014-05-08 16:59:35 +00:00
|
|
|
extra = 0
|
|
|
|
verbose_name_plural = _("Subdomains")
|
|
|
|
|
2015-04-02 16:14:55 +00:00
|
|
|
domain_link = admin_link('__str__')
|
2014-05-08 16:59:35 +00:00
|
|
|
domain_link.short_description = _("Name")
|
2014-10-24 11:10:30 +00:00
|
|
|
account_link = admin_link('account')
|
|
|
|
|
|
|
|
def display_records(self, domain):
|
2014-11-05 21:29:14 +00:00
|
|
|
return ', '.join([record.type for record in domain.records.all()])
|
2014-10-24 11:10:30 +00:00
|
|
|
display_records.short_description = _("Declared records")
|
2014-05-08 16:59:35 +00:00
|
|
|
|
|
|
|
def has_add_permission(self, *args, **kwargs):
|
|
|
|
return False
|
2014-11-05 21:29:14 +00:00
|
|
|
|
|
|
|
def get_queryset(self, request):
|
|
|
|
""" Order by structured name and imporve performance """
|
|
|
|
qs = super(DomainInline, self).get_queryset(request)
|
|
|
|
return qs.select_related('account').prefetch_related('records')
|
2014-05-08 16:59:35 +00:00
|
|
|
|
|
|
|
|
2014-11-05 21:29:14 +00:00
|
|
|
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
2014-07-17 16:09:24 +00:00
|
|
|
list_display = (
|
2015-04-03 13:03:08 +00:00
|
|
|
'structured_name', 'display_is_top', 'display_websites', 'account_link'
|
2014-07-17 16:09:24 +00:00
|
|
|
)
|
2014-10-27 13:29:02 +00:00
|
|
|
add_fields = ('name', 'account')
|
|
|
|
fields = ('name', 'account_link')
|
2015-07-20 12:51:30 +00:00
|
|
|
readonly_fields = ('account_link', 'top_link',)
|
|
|
|
inlines = (RecordInline, DomainInline)
|
|
|
|
list_filter = (TopDomainListFilter,)
|
2015-07-15 10:35:21 +00:00
|
|
|
change_readonly_fields = ('name', 'serial')
|
2015-04-24 11:39:20 +00:00
|
|
|
search_fields = ('name', 'account__username')
|
2015-03-11 20:01:08 +00:00
|
|
|
add_form = BatchDomainCreationAdminForm
|
2015-07-20 12:51:30 +00:00
|
|
|
actions = (edit_records, set_soa)
|
|
|
|
change_view_actions = (view_zone, edit_records)
|
|
|
|
|
|
|
|
top_link = admin_link('top')
|
2014-05-08 16:59:35 +00:00
|
|
|
|
|
|
|
def structured_name(self, domain):
|
2015-05-07 14:09:37 +00:00
|
|
|
if domain.is_top:
|
|
|
|
return domain.name
|
|
|
|
return ' '*4 + domain.name
|
2014-05-08 16:59:35 +00:00
|
|
|
structured_name.short_description = _("name")
|
|
|
|
structured_name.allow_tags = True
|
|
|
|
structured_name.admin_order_field = 'structured_name'
|
|
|
|
|
2014-07-17 16:09:24 +00:00
|
|
|
def display_is_top(self, domain):
|
|
|
|
return domain.is_top
|
2014-11-14 16:12:56 +00:00
|
|
|
display_is_top.short_description = _("Is top")
|
2014-07-17 16:09:24 +00:00
|
|
|
display_is_top.boolean = True
|
|
|
|
display_is_top.admin_order_field = 'top'
|
2014-05-08 16:59:35 +00:00
|
|
|
|
2015-04-03 13:03:08 +00:00
|
|
|
def display_websites(self, domain):
|
2015-04-05 10:46:24 +00:00
|
|
|
if apps.isinstalled('orchestra.contrib.websites'):
|
2014-05-08 16:59:35 +00:00
|
|
|
webs = domain.websites.all()
|
|
|
|
if webs:
|
|
|
|
links = []
|
|
|
|
for web in webs:
|
2014-09-18 15:07:39 +00:00
|
|
|
url = change_url(web)
|
2014-05-08 16:59:35 +00:00
|
|
|
links.append('<a href="%s">%s</a>' % (url, web.name))
|
|
|
|
return '<br>'.join(links)
|
|
|
|
return _("No website")
|
2015-04-03 13:03:08 +00:00
|
|
|
display_websites.admin_order_field = 'websites__name'
|
|
|
|
display_websites.short_description = _("Websites")
|
|
|
|
display_websites.allow_tags = True
|
2014-05-08 16:59:35 +00:00
|
|
|
|
2015-07-15 10:35:21 +00:00
|
|
|
def get_fieldsets(self, request, obj=None):
|
|
|
|
""" Add SOA fields when domain is top """
|
|
|
|
fieldsets = super(DomainAdmin, self).get_fieldsets(request, obj)
|
2015-07-20 12:51:30 +00:00
|
|
|
if obj:
|
|
|
|
if obj.is_top:
|
|
|
|
fieldsets += (
|
|
|
|
(_("SOA"), {
|
|
|
|
'classes': ('collapse',),
|
|
|
|
'fields': ('serial', 'refresh', 'retry', 'expire', 'min_ttl'),
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
existing = fieldsets[0][1]['fields']
|
|
|
|
if 'top_link' not in existing:
|
|
|
|
fieldsets[0][1]['fields'].insert(2, 'top_link')
|
2015-07-15 10:35:21 +00:00
|
|
|
return fieldsets
|
|
|
|
|
2015-07-20 12:51:30 +00:00
|
|
|
def get_inline_instances(self, request, obj=None):
|
|
|
|
inlines = super(DomainAdmin, self).get_inline_instances(request, obj)
|
|
|
|
if not obj or not obj.is_top:
|
|
|
|
return [inline for inline in inlines if type(inline) != DomainInline]
|
|
|
|
return inlines
|
|
|
|
|
2014-07-08 15:19:15 +00:00
|
|
|
def get_queryset(self, request):
|
2014-05-08 16:59:35 +00:00
|
|
|
""" Order by structured name and imporve performance """
|
2014-07-08 15:19:15 +00:00
|
|
|
qs = super(DomainAdmin, self).get_queryset(request)
|
2014-11-05 21:29:14 +00:00
|
|
|
qs = qs.select_related('top', 'account')
|
2015-04-09 14:32:10 +00:00
|
|
|
if request.method == 'GET':
|
2015-05-18 15:21:42 +00:00
|
|
|
qs = qs.annotate(
|
|
|
|
structured_id=Coalesce('top__id', 'id'),
|
|
|
|
structured_name=Concat('top__name', 'name')
|
|
|
|
).order_by('-structured_id', 'structured_name')
|
2015-04-05 10:46:24 +00:00
|
|
|
if apps.isinstalled('orchestra.contrib.websites'):
|
2014-05-08 16:59:35 +00:00
|
|
|
qs = qs.prefetch_related('websites')
|
|
|
|
return qs
|
2014-10-24 11:25:05 +00:00
|
|
|
|
2015-03-11 20:01:08 +00:00
|
|
|
def save_model(self, request, obj, form, change):
|
|
|
|
""" batch domain creation support """
|
|
|
|
super(DomainAdmin, self).save_model(request, obj, form, change)
|
|
|
|
self.extra_domains = []
|
|
|
|
if not change:
|
|
|
|
for name in form.extra_names:
|
|
|
|
domain = Domain.objects.create(name=name, account_id=obj.account_id)
|
|
|
|
self.extra_domains.append(domain)
|
|
|
|
|
|
|
|
def save_related(self, request, form, formsets, change):
|
|
|
|
""" batch domain creation support """
|
|
|
|
super(DomainAdmin, self).save_related(request, form, formsets, change)
|
|
|
|
if not change:
|
|
|
|
# Clone records to extra_domains, if any
|
|
|
|
for formset in formsets:
|
|
|
|
if formset.model is Record:
|
|
|
|
for domain in self.extra_domains:
|
|
|
|
# Reset pk value of the record instances to force creation of new ones
|
|
|
|
for record_form in formset.forms:
|
|
|
|
record = record_form.instance
|
|
|
|
if record.pk:
|
|
|
|
record.pk = None
|
|
|
|
formset.instance = domain
|
|
|
|
form.instance = domain
|
2015-07-20 12:51:30 +00:00
|
|
|
self.save_formset(request, form, formset, change)
|
2014-05-08 16:59:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
admin.site.register(Domain, DomainAdmin)
|