django-orchestra-test/orchestra/contrib/domains/admin.py

228 lines
9.4 KiB
Python
Raw Permalink Normal View History

2014-05-08 16:59:35 +00:00
from django.contrib import admin
from django.urls import reverse
2016-04-27 08:35:13 +00:00
from django.db import models
2015-05-18 15:21:42 +00:00
from django.db.models.functions import Concat, Coalesce
2016-03-11 12:19:34 +00:00
from django.templatetags.static import static
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext, gettext_lazy as _
2014-05-08 16:59:35 +00:00
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
from orchestra.contrib.accounts.actions import list_accounts
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
from orchestra.utils.html import get_on_site_link
2014-05-08 16:59:35 +00:00
2016-03-09 10:06:26 +00:00
from . import settings
from .actions import view_zone, edit_records, set_soa
2016-03-09 11:16:28 +00:00
from .filters import TopDomainListFilter, HasWebsiteFilter, HasAddressFilter
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
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')
2014-10-24 11:10:30 +00:00
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 = (
2016-04-27 08:35:13 +00:00
'structured_name', 'display_is_top', 'display_websites', 'display_addresses', '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', 'display_websites', 'display_addresses', 'dns2136_address_match_list')
2016-04-27 08:35:13 +00:00
readonly_fields = (
'account_link', 'top_link', 'display_websites', 'display_addresses', 'implicit_records'
)
inlines = (RecordInline, DomainInline)
2016-03-09 11:16:28 +00:00
list_filter = (TopDomainListFilter, HasWebsiteFilter, HasAddressFilter)
2015-07-15 10:35:21 +00:00
change_readonly_fields = ('name', 'serial')
2015-07-27 12:55:35 +00:00
search_fields = ('name', 'account__username', 'records__value')
2015-03-11 20:01:08 +00:00
add_form = BatchDomainCreationAdminForm
actions = (edit_records, set_soa, list_accounts)
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):
if domain.is_top:
return domain.name
return mark_safe(' '*4 + domain.name)
2014-05-08 16:59:35 +00:00
structured_name.short_description = _("name")
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'
@mark_safe
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'):
2015-09-29 08:45:47 +00:00
websites = domain.websites.all()
if websites:
2014-05-08 16:59:35 +00:00
links = []
2015-09-29 08:45:47 +00:00
for website in websites:
site_link = get_on_site_link(website.get_absolute_url())
2015-09-29 08:45:47 +00:00
admin_url = change_url(website)
2016-02-19 10:11:28 +00:00
title = _("Edit website")
link = format_html('<a href="{}" title="{}">{} {}</a>',
2016-02-19 10:11:28 +00:00
admin_url, title, website.name, site_link)
2015-09-29 08:45:47 +00:00
links.append(link)
2014-05-08 16:59:35 +00:00
return '<br>'.join(links)
2016-04-27 08:35:13 +00:00
add_url = reverse('admin:websites_website_add')
add_url += '?account=%i&domains=%i' % (domain.account_id, domain.pk)
add_link = format_html(
'<a href="{}" title="{}"><img src="{}" /></a>', add_url,
_("Add website"), static('orchestra/images/add.png'),
2016-04-27 08:35:13 +00:00
)
return _("No website %s") % (add_link)
return '---'
2015-04-03 13:03:08 +00:00
display_websites.admin_order_field = 'websites__name'
display_websites.short_description = _("Websites")
@mark_safe
2016-04-27 08:35:13 +00:00
def display_addresses(self, domain):
if apps.isinstalled('orchestra.contrib.mailboxes'):
add_url = reverse('admin:mailboxes_address_add')
add_url += '?account=%i&domain=%i' % (domain.account_id, domain.pk)
image = '<img src="%s"></img>' % static('orchestra/images/add.png')
add_link = '<a href="%s" title="%s">%s</a>' % (
add_url, _("Add address"), image
)
addresses = domain.addresses.all()
if addresses:
url = reverse('admin:mailboxes_address_changelist')
url += '?domain=%i' % addresses[0].domain_id
title = '\n'.join([address.email for address in addresses])
return '<a href="%s" title="%s">%s</a> %s' % (url, title, len(addresses), add_link)
return _("No address %s") % (add_link)
return '---'
display_addresses.short_description = _("Addresses")
display_addresses.admin_order_field = 'addresses__count'
@mark_safe
2016-03-09 10:06:26 +00:00
def implicit_records(self, domain):
types = set(domain.records.values_list('type', flat=True))
ttl = settings.DOMAINS_DEFAULT_TTL
lines = []
for record in domain.get_default_records():
line = '{name} {ttl} IN {type} {value}'.format(
name=domain.name,
ttl=ttl,
type=record.type,
value=record.value
)
if not domain.record_is_implicit(record, types):
line = format_html('<strike>{}</strike>', line)
2016-03-09 10:06:26 +00:00
if record.type is Record.SOA:
lines.insert(0, line)
else:
lines.append(line)
return '<br>'.join(lines)
implicit_records.short_description = _("Implicit records")
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)
if obj:
2016-03-09 10:06:26 +00:00
fieldsets += (
(_("Implicit records"), {
'classes': ('collapse',),
'fields': ('implicit_records',),
}),
)
if obj.is_top:
fieldsets += (
(_("SOA"), {
'classes': ('collapse',),
2016-02-23 11:49:10 +00:00
'description': _(
2016-04-30 12:01:29 +00:00
"SOA (Start of Authority) records are used to determine how the "
2016-02-23 11:49:10 +00:00
"zone propagates to the secondary nameservers."),
'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
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'):
2016-02-19 10:11:28 +00:00
qs = qs.prefetch_related('websites__domains')
2016-04-27 08:35:13 +00:00
if apps.isinstalled('orchestra.contrib.mailboxes'):
qs = qs.annotate(models.Count('addresses'))
2014-05-08 16:59:35 +00:00
return qs
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)
2015-03-11 20:01:08 +00:00
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
self.save_formset(request, form, formset, change)
2014-05-08 16:59:35 +00:00
admin.site.register(Domain, DomainAdmin)